Repository: jensneuse/graphql-go-tools
Pull request #148 (2019-12-16 12:36:56)

feature/improve docs
This PR extends the existing documentation using godoc in an effort to make the library more approachable.


Patch:
diff --git a/README.md b/README.md
index 75023320..2ce173c5 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ This repos uses go modules so make sure to use the latest version of Go.
 
 ## Docs
 
-https://jens-neuse.gitbook.io/graphql-go-tools
+https://godoc.org/github.com/jensneuse/graphql-go-tools
 
 ## Usage
 
diff --git a/doc.go b/doc.go
new file mode 100644
index 00000000..3018fd69
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,28 @@
+// Package graphql-go-tools is library to create GraphQL services using the go programming language.
+//
+// About GraphQL
+//
+// GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
+//
+// Source: https://graphql.org
+//
+// About this library
+//
+// This library is intended to be a set of low level building blocks to write high performance and secure GraphQL applications.
+// Use cases could range from writing layer seven GraphQL proxies, firewalls, caches etc..
+// You would usually not use this library to write a GraphQL server yourself but to build tools for the GraphQL ecosystem.
+//
+// To achieve this goal the library has zero dependencies at its core functionality.
+// It has a full implementation of the GraphQL AST and supports lexing, parsing, validation, normalization, introspection, query planning as well as query execution etc.
+//
+// With the execution package it's possible to write a fully functional GraphQL server that is capable to mediate between various protocols and formats.
+// In it's current state you can use the following DataSources to resolve fields:
+// - Static data (embed static data into a schema to extend a field in a simple way)
+// - HTTP JSON APIs (combine multiple Restful APIs into one single GraphQL Endpoint, nesting is possible)
+// - GraphQL APIs (you can combine multiple GraphQL APIs into one single GraphQL Endpoint, nesting is possible)
+// - Webassembly/WASM Lambdas (e.g. resolve a field using a Rust lambda)
+//
+// If you're looking for a ready to use solution that has all this functionality packaged as a Gateway have a look at: https://github.com/jensneuse/graphql-gateway
+//
+// Created by Jens Neuse
+package graphql_go_tools
diff --git a/go.mod b/go.mod
index 14d4a700..b88bbae8 100644
--- a/go.mod
+++ b/go.mod
@@ -23,6 +23,7 @@ require (
 	go.uber.org/atomic v1.4.0 // indirect
 	go.uber.org/multierr v1.2.0 // indirect
 	go.uber.org/zap v1.11.0
+	golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935 // indirect
 	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
 	gopkg.in/yaml.v2 v2.2.4 // indirect
 )
diff --git a/go.sum b/go.sum
index ad93fe06..1397c4c3 100644
--- a/go.sum
+++ b/go.sum
@@ -125,9 +125,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
 golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
 golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -139,6 +144,10 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c h1:KfpJVdWhuRqNk4XVXzjXf2KAV4TBEP77SYdFGjeGuIE=
 golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935 h1:kJQZhwFzSwJS2BxboKjdZzWczQOZx8VuH7Y8hhuGUtM=
+golang.org/x/tools v0.0.0-20191213221258-04c2e8eff935/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
diff --git a/pkg/ast/ast.go b/pkg/ast/ast.go
index 20767324..8e85dacd 100644
--- a/pkg/ast/ast.go
+++ b/pkg/ast/ast.go
@@ -1,4 +1,8 @@
 //go:generate stringer -type=OperationType,ValueKind,TypeKind,SelectionKind,NodeKind,PathKind -output ast_string.go
+
+// Package ast defines the GraphQL AST and offers helper methods to interact with the AST, mostly to get the necessary information from the ast.
+//
+// The document struct is designed in a way to enable performant parsing while keeping the ast easy to use with helper methods.
 package ast
 
 import (
diff --git a/pkg/ast/directivelocation.go b/pkg/ast/directivelocation.go
index e858c403..a4b8cc62 100644
--- a/pkg/ast/directivelocation.go
+++ b/pkg/ast/directivelocation.go
@@ -1,4 +1,5 @@
 //go:generate stringer -type=DirectiveLocation
+
 package ast
 
 import "fmt"
diff --git a/pkg/ast/index.go b/pkg/ast/index.go
index e51a87d9..060f9da0 100644
--- a/pkg/ast/index.go
+++ b/pkg/ast/index.go
@@ -2,14 +2,25 @@ package ast
 
 // Index is a struct to easily look up objects in a document, e.g. find Nodes (type/interface/union definitions) by name
 type Index struct {
+	// QueryTypeName is the name of the query type on the schema Node
+	// schema { query: Query }
 	QueryTypeName           ByteSlice
+	// MutationTypeName is the name of the mutation type on the schema Node
+	// schema { mutation: Mutation }
 	MutationTypeName        ByteSlice
+	// SubscriptionTypeName is the name of the subscription type on the schema Node
+	// schema { subscription: Subscription }
 	SubscriptionTypeName    ByteSlice
+	// Nodes is a list of all root nodes in a schema definition
+	// The map key is the result of the xxhash algorithm from the Node name.
 	Nodes                   map[uint64]Node
+	// ReplacedFragmentSpreads is a list of references (slice indices) of all FragmentSpreads that got replaced during normalization.
 	ReplacedFragmentSpreads []int
+	// MergedTypeExtensions is a list of Nodes (Node kind + reference) that got merged during type extension merging.
 	MergedTypeExtensions    []Node
 }
 
+// Reset empties the Index
 func (i *Index) Reset() {
 	i.QueryTypeName = i.QueryTypeName[:0]
 	i.MutationTypeName = i.MutationTypeName[:0]
diff --git a/pkg/ast/input.go b/pkg/ast/input.go
index f0940448..553e1ed7 100644
--- a/pkg/ast/input.go
+++ b/pkg/ast/input.go
@@ -7,7 +7,7 @@ import (
 	"github.com/jensneuse/graphql-go-tools/pkg/lexer/position"
 )
 
-// RawBytes is a raw graphql document containing the raw input + meta data
+// Input is a raw graphql document containing the raw input + meta data
 type Input struct {
 	// RawBytes is the raw byte input
 	RawBytes []byte
@@ -19,22 +19,26 @@ type Input struct {
 	TextPosition position.Position
 }
 
+// Reset empties the Input
 func (i *Input) Reset() {
 	i.RawBytes = i.RawBytes[:0]
 	i.InputPosition = 0
 	i.TextPosition.Reset()
 }
 
+// ResetInputBytes empties the input and sets it to bytes argument
 func (i *Input) ResetInputBytes(bytes []byte) {
 	i.Reset()
 	i.AppendInputBytes(bytes)
 	i.Length = len(i.RawBytes)
 }
 
+// ResetInputString empties the input and sets it to input string.
 func (i *Input) ResetInputString(input string) {
 	i.ResetInputBytes([]byte(input))
 }
 
+// AppendInputBytes appends a byte slice to the current input and returns the ByteSliceReference
 func (i *Input) AppendInputBytes(bytes []byte) (ref ByteSliceReference) {
 	ref.Start = uint32(len(i.RawBytes))
 	i.RawBytes = append(i.RawBytes, bytes...)
@@ -43,18 +47,22 @@ func (i *Input) AppendInputBytes(bytes []byte) (ref ByteSliceReference) {
 	return
 }
 
-func (i *Input) AppendInputString(input string) {
-	i.AppendInputBytes([]byte(input))
+// AppendInputString appends a string to the current input and returns the ByteSliceReference
+func (i *Input) AppendInputString(input string) ByteSliceReference {
+	return i.AppendInputBytes([]byte(input))
 }
 
+// ByteSlice returns the byte slice for a given byte ByteSliceReference
 func (i *Input) ByteSlice(reference ByteSliceReference) ByteSlice {
 	return i.RawBytes[reference.Start:reference.End]
 }
 
+// ByteSliceString returns a string for a given ByteSliceReference
 func (i *Input) ByteSliceString(reference ByteSliceReference) string {
 	return unsafebytes.BytesToString(i.ByteSlice(reference))
 }
 
+// ByteSliceReferenceContentEquals compares the content of two byte slices and returns true if they are the same
 func (i *Input) ByteSliceReferenceContentEquals(left, right ByteSliceReference) bool {
 	if left.Length() != right.Length() {
 		return false
@@ -68,8 +76,10 @@ func (i *Input) ByteSliceReferenceContentEquals(left, right ByteSliceReference)
 	return true
 }
 
+// ByteSlice is an alias for []byte
 type ByteSlice []byte
 
+// Equals compares a ByteSlice to another
 func (b ByteSlice) Equals(another ByteSlice) bool {
 	if len(b) != len(another) {
 		return false
@@ -108,6 +118,7 @@ func (b ByteSliceReference) Length() uint32 {
 	return b.End - b.Start
 }
 
+// ByteSliceEquals compares two ByteSliceReferences from different Inputs
 func ByteSliceEquals(left ByteSliceReference, leftInput Input, right ByteSliceReference, rightInput Input) bool {
 	if left.Length() != right.Length() {
 		return false
diff --git a/pkg/astimport/astimport.go b/pkg/astimport/astimport.go
index 43d8b111..8ac6a9c8 100644
--- a/pkg/astimport/astimport.go
+++ b/pkg/astimport/astimport.go
@@ -1,3 +1,6 @@
+// Package astimport can be used to import Nodes manually into an AST.
+//
+// This is useful when an AST should be created manually.
 package astimport
 
 import (
@@ -6,12 +9,15 @@ import (
 	"github.com/jensneuse/graphql-go-tools/pkg/operationreport"
 )
 
+// Importer imports Nodes into an existing AST.
+// Always use NewImporter() to create a new Importer.
 type Importer struct {
 	doc    *ast.Document
 	parser *astparser.Parser
 	report *operationreport.Report
 }
 
+// NewImporter creates a default Importer
 func NewImporter() *Importer {
 	return &Importer{
 		parser: astparser.NewParser(),
@@ -24,9 +30,10 @@ func (i *Importer) prepare (inputBytes []byte) {
 	i.doc.Reset()
 	i.report.Reset()
 	i.doc.Input.ResetInputBytes(inputBytes)
-	i.parser.Prepare(i.doc, i.report)
+	i.parser.PrepareImport(i.doc, i.report)
 }
 
+// ImportType imports a Type in GraphQL format into the provided AST.
 func (i *Importer) ImportType(typeBytes []byte, document *ast.Document) int {
 	i.prepare(typeBytes)
 	ref := i.parser.ParseType()
diff --git a/pkg/astnormalization/astnormalization.go b/pkg/astnormalization/astnormalization.go
index 5a3183b7..abfe701b 100644
--- a/pkg/astnormalization/astnormalization.go
+++ b/pkg/astnormalization/astnormalization.go
@@ -1,3 +1,70 @@
+/*Package astnormalization helps to transform parsed GraphQL AST's into a easier to use structure.
+
+Example
+
+This examples shows how the normalization package helps "simplifying" a GraphQL AST.
+
+Input:
+
+ subscription sub {
+ 	... multipleSubscriptions
+	... on Subscription {
+		newMessage {
+			body
+			sender
+		}
+	}
+ }
+ fragment newMessageFields on Message {
+ 	body: body
+ 	sender
+ 	... on Body {
+ 		body
+ 	}
+ }
+ fragment multipleSubscriptions on Subscription {
+ 	newMessage {
+ 		body
+ 		sender
+ 	}
+ 	newMessage {
+ 		... newMessageFields
+ 	}
+ 	newMessage {
+ 		body
+ 		body
+		sender
+ 	}
+ 	... on Subscription {
+ 		newMessage {
+ 			body
+ 			sender
+ 		}
+ 	}
+ 	disallowedSecondRootField
+ }
+
+Output:
+
+ subscription sub {
+ 	newMessage {
+ 		body
+ 		sender
+ 	}
+ 	disallowedSecondRootField
+ }
+ fragment newMessageFields on Message {
+ 	body
+ 	sender
+ }
+ fragment multipleSubscriptions on Subscription {
+ 	newMessage {
+ 		body
+ 		sender
+ 	}
+ 	disallowedSecondRootField
+ }
+*/
 package astnormalization
 
 import (
@@ -6,6 +73,9 @@ import (
 	"github.com/jensneuse/graphql-go-tools/pkg/operationreport"
 )
 
+// NormalizeOperation creates a default Normalizer and applies all rules to a given AST
+// In case you're using OperationNormalizer in a hot path you shouldn't be using this function.
+// Create a new OperationNormalizer using NewNormalizer() instead and re-use it.
 func NormalizeOperation(operation, definition *ast.Document, report *operationreport.Report) {
 	normalizer := NewNormalizer(false)
 	normalizer.NormalizeOperation(operation, definition, report)
@@ -13,11 +83,13 @@ func NormalizeOperation(operation, definition *ast.Document, report *operationre
 
 type registerNormalizeFunc func(walker *astvisitor.Walker)
 
+// OperationNormalizer walks a given AST and applies all registered rules
 type OperationNormalizer struct {
 	walkers                   []*astvisitor.Walker
 	removeFragmentDefinitions bool
 }
 
+// NewNormalizer creates a new OperationNormalizer and sets up all default rules
 func NewNormalizer(removeFragmentDefinitions bool) *OperationNormalizer {
 	normalizer := &OperationNormalizer{
 		removeFragmentDefinitions: removeFragmentDefinitions,
@@ -43,6 +115,7 @@ func (o *OperationNormalizer) setupWalkers() {
 	o.walkers = append(o.walkers, &fragmentInline, &other)
 }
 
+// NormalizeOperation applies all registered rules to the AST
 func (o *OperationNormalizer) NormalizeOperation(operation, definition *ast.Document, report *operationreport.Report) {
 	for i := range o.walkers {
 		o.walkers[i].Walk(operation, definition, report)
diff --git a/pkg/astnormalization/fragmentspread_depth.go b/pkg/astnormalization/fragmentspread_depth.go
index 0f9a205d..57390553 100644
--- a/pkg/astnormalization/fragmentspread_depth.go
+++ b/pkg/astnormalization/fragmentspread_depth.go
@@ -7,13 +7,15 @@ import (
 	"github.com/jensneuse/graphql-go-tools/pkg/operationreport"
 )
 
+// FragmentSpreadDepth is a helper for nested Fragments to calculate the actual depth of a Fragment Node
 type FragmentSpreadDepth struct {
 	walker             astvisitor.Walker
 	visitor            fragmentSpreadDepthVisitor
-	calc               NestedDepthCalc
+	calc               nestedDepthCalc
 	visitorsRegistered bool
 }
 
+// Depth holds all necessary information to understand the Depth of a Fragment Node
 type Depth struct {
 	SpreadRef          int
 	Depth              int
@@ -33,6 +35,7 @@ func (d Depths) ByRef(ref int) (int, bool) {
 	return -1, false
 }
 
+// Get returns all FragmentSpread Depths for a given AST
 func (r *FragmentSpreadDepth) Get(operation, definition *ast.Document, report *operationreport.Report, depths *Depths) {
 
 	if !r.visitorsRegistered {
@@ -49,11 +52,11 @@ func (r *FragmentSpreadDepth) Get(operation, definition *ast.Document, report *o
 	r.calc.calculatedNestedDepths(depths)
 }
 
-type NestedDepthCalc struct {
+type nestedDepthCalc struct {
 	depths *Depths
 }
 
-func (n *NestedDepthCalc) calculatedNestedDepths(depths *Depths) {
+func (n *nestedDepthCalc) calculatedNestedDepths(depths *Depths) {
 	n.depths = depths
 
 	for i := range *depths {
@@ -61,14 +64,14 @@ func (n *NestedDepthCalc) calculatedNestedDepths(depths *Depths) {
 	}
 }
 
-func (n *NestedDepthCalc) calculateNestedDepth(i int) int {
+func (n *nestedDepthCalc) calculateNestedDepth(i int) int {
 	if !(*n.depths)[i].isNested {
 		return (*n.depths)[i].Depth
 	}
 	return (*n.depths)[i].Depth + n.depthForFragment((*n.depths)[i].parentFragmentName)
 }
 
-func (n *NestedDepthCalc) depthForFragment(name ast.ByteSlice) int {
+func (n *nestedDepthCalc) depthForFragment(name ast.ByteSlice) int {
 	for i := range *n.depths {
 		if bytes.Equal(name, (*n.depths)[i].SpreadName) {
 			return n.calculateNestedDepth(i)
diff --git a/pkg/astparser/parser.go b/pkg/astparser/parser.go
index 7659e508..2883f658 100644
--- a/pkg/astparser/parser.go
+++ b/pkg/astparser/parser.go
@@ -1,3 +1,4 @@
+// Package astparser is used to turn raw GraphQL documents into an AST.
 package astparser
 
 import (
@@ -14,15 +15,18 @@ import (
 	"runtime"
 )
 
+// ParseGraphqlDocumentString takes a raw GraphQL document in string format and parses it into an AST.
+// This function creates a new parser as well as a new AST for every call.
+// Therefore you shouldn't use this function in a hot path.
+// Instead create a parser as well as AST objects and re-use them.
 func ParseGraphqlDocumentString(input string) (ast.Document, operationreport.Report) {
-	parser := NewParser()
-	doc := *ast.NewDocument()
-	doc.Input.ResetInputString(input)
-	report := operationreport.Report{}
-	parser.Parse(&doc, &report)
-	return doc, report
+	return ParseGraphqlDocumentBytes([]byte(input))
 }
 
+// ParseGraphqlDocumentBytes takes a raw GraphQL document in byte slice format and parses it into an AST.
+// This function creates a new parser as well as a new AST for every call.
+// Therefore you shouldn't use this function in a hot path.
+// Instead create a parser as well as AST objects and re-use them.
 func ParseGraphqlDocumentBytes(input []byte) (ast.Document, operationreport.Report) {
 	parser := NewParser()
 	doc := *ast.NewDocument()
@@ -38,6 +42,7 @@ type origin struct {
 	funcName string
 }
 
+// ErrUnexpectedToken is a custom error object containing all necessary information to properly render an unexpected token error
 type ErrUnexpectedToken struct {
 	keyword  keyword.Keyword
 	expected []keyword.Keyword
@@ -56,6 +61,7 @@ func (e ErrUnexpectedToken) Error() string {
 	return fmt.Sprintf("unexpected token - keyword: '%s' literal: '%s' - expected: '%s' position: '%s'%s", e.keyword, e.literal, e.expected, e.position, origins)
 }
 
+// ErrUnexpectedIdentKey is a custom error object to properly render an unexpected ident key error
 type ErrUnexpectedIdentKey struct {
 	keyword  identkeyword.IdentKeyword
 	expected []identkeyword.IdentKeyword
@@ -74,6 +80,9 @@ func (e ErrUnexpectedIdentKey) Error() string {
 	return fmt.Sprintf("unexpected ident - keyword: '%s' literal: '%s' - expected: '%s' position: '%s'%s", e.keyword, e.literal, e.expected, e.position, origins)
 }
 
+// Parser takes a raw input and turns it into an AST
+// use NewParser() to create a parser
+// Don't create new parsers in the hot path, re-use them.
 type Parser struct {
 	document             *ast.Document
 	report               *operationreport.Report
@@ -85,6 +94,7 @@ type Parser struct {
 	reportInternalErrors bool
 }
 
+// NewParser returns a new parser with all values properly initialized
 func NewParser() *Parser {
 	return &Parser{
 		tokens:               make([]token.Token, 256),
@@ -94,13 +104,15 @@ func NewParser() *Parser {
 	}
 }
 
-func (p *Parser) Prepare (document *ast.Document, report *operationreport.Report) {
+// PrepareImport prepares the Parser for importing new Nodes into an AST without directly parsing the content
+func (p *Parser) PrepareImport(document *ast.Document, report *operationreport.Report) {
 	p.document = document
 	p.report = report
 	p.lexer.SetInput(&document.Input)
 	p.tokenize()
 }
 
+// Parse parses all input in a Document.Input into the Document
 func (p *Parser) Parse(document *ast.Document, report *operationreport.Report) {
 	p.document = document
 	p.report = report
diff --git a/pkg/astprinter/astprinter.go b/pkg/astprinter/astprinter.go
index f6e1c881..259f5517 100644
--- a/pkg/astprinter/astprinter.go
+++ b/pkg/astprinter/astprinter.go
@@ -1,3 +1,4 @@
+// Package astprinter takes a GraphQL document and prints it as a String with optional indentation.
 package astprinter
 
 import (
@@ -8,11 +9,14 @@ import (
 	"io"
 )
 
+// Print takes a document as well as a definition (optional) and prints it to the io.Writer.
+// The definition is only necessary in case a GraphQL Operation should be printed.
 func Print(document, definition *ast.Document, out io.Writer) error {
 	printer := Printer{}
 	return printer.Print(document, definition, out)
 }
 
+// PrintIndent is the same as Print but accepts an additional indent parameter to set indentation.
 func PrintIndent(document, definition *ast.Document, indent []byte, out io.Writer) error {
 	printer := Printer{
 		indent: indent,
@@ -20,6 +24,7 @@ func PrintIndent(document, definition *ast.Document, indent []byte, out io.Write
 	return printer.Print(document, definition, out)
 }
 
+// PrintString is the same as Print but returns a string instead of writing to an io.Writer
 func PrintString(document, definition *ast.Document) (string, error) {
 	buff := &bytes.Buffer{}
 	err := Print(document, definition, buff)
@@ -27,6 +32,7 @@ func PrintString(document, definition *ast.Document) (string, error) {
 	return out, err
 }
 
+// PrintStringIndent is the same as PrintIndent but returns a string instead of writing to an io.Writer
 func PrintStringIndent(document, definition *ast.Document, indent string) (string, error) {
 	buff := &bytes.Buffer{}
 	err := PrintIndent(document, definition, []byte(indent), buff)
@@ -34,6 +40,7 @@ func PrintStringIndent(document, definition *ast.Document, indent string) (strin
 	return out, err
 }
 
+// Printer walks a GraphQL document and prints it as a string
 type Printer struct {
 	indent     []byte
 	visitor    printVisitor
@@ -41,6 +48,8 @@ type Printer struct {
 	registered bool
 }
 
+// Print starts the actual AST printing
+// Keep a printer and re-use it in case you'd like to print ASTs in the hot path.
 func (p *Printer) Print(document, definition *ast.Document, out io.Writer) error {
 	p.visitor.indent = p.indent
 	p.visitor.err = nil
diff --git a/pkg/asttransform/asttransform.go b/pkg/asttransform/asttransform.go
index cb7859df..1478b8ec 100644
--- a/pkg/asttransform/asttransform.go
+++ b/pkg/asttransform/asttransform.go
@@ -1,3 +1,13 @@
+// Package asttransform contains a set of helper methods to make recursive ast transformations possible.
+//
+// This is especially useful for ast normalization for nested fragment inlining.
+//
+// This packages is necessary to make AST transformations possible while walking an AST recusively.
+// In order to resolve dependencies in a tree (inline fragments & fragment spreads) it's necessary to resolve them in a specific order.
+// The right order to not mess things up is from the deepest level up to the root.
+// Therefore this package is used to register transformations while walking an AST in order to bring all transformations in the right order.
+// Only then, when all transformations are in the right order according to depth, it's possible to safely apply them.
+//
 package asttransform
 
 import (
@@ -6,42 +16,44 @@ import (
 )
 
 type (
+	// Transformable defines the interface which needs to be implemented in order to apply Transformations
+	// This needs to be implemented by any AST in order to be transformable
 	Transformable interface {
+		// DeleteRootNode marks a Node for deletion
 		DeleteRootNode(node ast.Node)
+		// EmptySelectionSet marks a selectionset for emptying
 		EmptySelectionSet(ref int)
+		// AppendSelectionSet marks to append a reference to a selectionset
 		AppendSelectionSet(ref int, appendRef int)
+		// ReplaceFragmentSpread marks to replace a fragment spread with a selectionset
 		ReplaceFragmentSpread(selectionSet int, spreadRef int, replaceWithSelectionSet int)
+		// ReplaceFragmentSpreadWithInlineFragment marks a fragment spread to be replaces with an inline fragment
 		ReplaceFragmentSpreadWithInlineFragment(selectionSet int, spreadRef int, replaceWithSelectionSet int, typeCondition ast.TypeCondition)
 	}
 	transformation interface {
 		apply(transformable Transformable)
 	}
+	// Precedence defines Depth and Order of each transformation
 	Precedence struct {
 		Depth int
 		Order int
-		last  int
 	}
 	action struct {
 		precedence     Precedence
 		transformation transformation
 	}
+	// Transformer takes transformation registrations and applies them
 	Transformer struct {
 		actions []action
 	}
 )
 
-func (p *Precedence) Next() Precedence {
-	p.last++
-	return Precedence{
-		Depth: p.Depth,
-		Order: p.last,
-	}
-}
-
+// Reset empties all actions
 func (t *Transformer) Reset() {
 	t.actions = t.actions[:0]
 }
 
+// ApplyTransformations applies all registered transformations to a transformable
 func (t *Transformer) ApplyTransformations(transformable Transformable) {
 
 	sort.Slice(t.actions, func(i, j int) bool {
@@ -56,6 +68,7 @@ func (t *Transformer) ApplyTransformations(transformable Transformable) {
 	}
 }
 
+// DeleteRootNode registers an action to delete a root node
 func (t *Transformer) DeleteRootNode(precedence Precedence, node ast.Node) {
 	t.actions = append(t.actions, action{
 		precedence:     precedence,
@@ -63,6 +76,7 @@ func (t *Transformer) DeleteRootNode(precedence Precedence, node ast.Node) {
 	})
 }
 
+// EmptySelectionSet registers an actions to empty a selectionset
 func (t *Transformer) EmptySelectionSet(precedence Precedence, ref int) {
 	t.actions = append(t.actions, action{
 		precedence:     precedence,
@@ -70,6 +84,7 @@ func (t *Transformer) EmptySelectionSet(precedence Precedence, ref int) {
 	})
 }
 
+// AppendSelectionSet registers an action to append a selection to a selectionset
 func (t *Transformer) AppendSelectionSet(precedence Precedence, ref int, appendRef int) {
 	t.actions = append(t.actions, action{
 		precedence: precedence,
@@ -80,6 +95,7 @@ func (t *Transformer) AppendSelectionSet(precedence Precedence, ref int, appendR
 	})
 }
 
+// ReplaceFragmentSpread registers an action to replace a fragment spread with a selectionset
 func (t *Transformer) ReplaceFragmentSpread(precedence Precedence, selectionSet int, spreadRef int, replaceWithSelectionSet int) {
 	t.actions = append(t.actions, action{
 		precedence: precedence,
@@ -91,6 +107,7 @@ func (t *Transformer) ReplaceFragmentSpread(precedence Precedence, selectionSet
 	})
 }
 
+// ReplaceFragmentSpreadWithInlineFragment registers an action to replace a fragment spread with an inline fragment
 func (t *Transformer) ReplaceFragmentSpreadWithInlineFragment(precedence Precedence, selectionSet int, spreadRef int, replaceWithSelectionSet int, typeCondition ast.TypeCondition) {
 	t.actions = append(t.actions, action{
 		precedence: precedence,
diff --git a/pkg/astvalidation/astvalidation.go b/pkg/astvalidation/astvalidation.go
index c13b6d32..8c93d1db 100644
--- a/pkg/astvalidation/astvalidation.go
+++ b/pkg/astvalidation/astvalidation.go
@@ -1,4 +1,6 @@
 //go:generate stringer -type=ValidationState -output astvalidation_string.go
+
+// Package astvalidation implements the validation rules specified in the GraphQL specification.
 package astvalidation
 
 import (
@@ -11,6 +13,7 @@ import (
 	"github.com/jensneuse/graphql-go-tools/pkg/operationreport"
 )
 
+// DefaultOperationValidator returns a fully initialized OperationValidator with all default rules registered
 func DefaultOperationValidator() *OperationValidator {
 
 	validator := OperationValidator{
@@ -38,6 +41,7 @@ func DefaultOperationValidator() *OperationValidator {
 	return &validator
 }
 
+// ValidationState is the outcome of a validation
 type ValidationState int
 
 const (
@@ -46,16 +50,20 @@ const (
 	Invalid
 )
 
+// Rule is hook to register callback functions on the Walker
 type Rule func(walker *astvisitor.Walker)
 
+// OperationValidator orchestrates the validation process of Operations
 type OperationValidator struct {
 	walker astvisitor.Walker
 }
 
+// RegisterRule registers a rule to the OperationValidator
 func (o *OperationValidator) RegisterRule(rule Rule) {
 	rule(&o.walker)
 }
 
+// Validate validates the operation against the definition using the registered ruleset.
 func (o *OperationValidator) Validate(operation, definition *ast.Document, report *operationreport.Report) ValidationState {
 
 	if report == nil {
@@ -70,6 +78,7 @@ func (o *OperationValidator) Validate(operation, definition *ast.Document, repor
 	return Valid
 }
 
+// OperationNameUniqueness validates if all operation names are unique
 func OperationNameUniqueness() Rule {
 	return func(walker *astvisitor.Walker) {
 		walker.RegisterEnterDocumentVisitor(&operationNameUniquenessVisitor{walker})
@@ -103,6 +112,7 @@ func (o *operationNameUniquenessVisitor) EnterDocument(operation, definition *as
 	}
 }
 
+// LoneAnonymousOperation validates if anonymous operations are alone in a given document.
 func LoneAnonymousOperation() Rule {
 	return func(walker *astvisitor.Walker) {
 		walker.RegisterEnterDocumentVisitor(&loneAnonymousOperationVisitor{walker})
@@ -126,6 +136,7 @@ func (l *loneAnonymousOperationVisitor) EnterDocument(operation, definition *ast
 	}
 }
 
+// SubscriptionSingleRootField validates if subscriptions have a single root field
 func SubscriptionSingleRootField() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := subscriptionSingleRootFieldVisitor{walker}
@@ -155,6 +166,7 @@ func (s *subscriptionSingleRootFieldVisitor) EnterDocument(operation, definition
 	}
 }
 
+// FieldSelections validates if all FieldSelections are possible and valid
 func FieldSelections() Rule {
 	return func(walker *astvisitor.Walker) {
 		fieldDefined := fieldDefined{
@@ -229,6 +241,7 @@ func (f *fieldDefined) EnterField(ref int) {
 	}
 }
 
+// FieldSelectionMerging validates if field selections can be merged
 func FieldSelectionMerging() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := fieldSelectionMergingVisitor{Walker: walker}
@@ -448,6 +461,7 @@ func (f *fieldSelectionMergingVisitor) EnterSelectionSet(ref int) {
 
 }
 
+// ValidArguments validates if arguments are valid
 func ValidArguments() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := validArgumentsVisitor{
@@ -624,6 +638,7 @@ func (v *validArgumentsVisitor) operationTypeSatisfiesDefinitionType(operationTy
 	}
 }
 
+// Values validates if values are used properly
 func Values() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := valuesVisitor{
@@ -830,6 +845,7 @@ func (v *valuesVisitor) valueSatisfiesScalar(value ast.Value, scalar int) bool {
 	}
 }
 
+// ArgumentUniqueness validates if arguments are unique
 func ArgumentUniqueness() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := argumentUniquenessVisitor{
@@ -862,6 +878,7 @@ func (a *argumentUniquenessVisitor) EnterArgument(ref int) {
 	}
 }
 
+// RequiredArguments validates if all required arguments are present
 func RequiredArguments() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := requiredArgumentsVisitor{
@@ -907,6 +924,7 @@ func (r *requiredArgumentsVisitor) EnterField(ref int) {
 	}
 }
 
+// Fragments validates if the use of fragments in a given document is correct
 func Fragments() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := fragmentsVisitor{
@@ -1011,6 +1029,7 @@ func (f *fragmentsVisitor) EnterFragmentDefinition(ref int) {
 	f.fragmentDefinitionsVisited = append(f.fragmentDefinitionsVisited, fragmentDefinitionName)
 }
 
+// DirectivesAreDefined validates if used directives are defined
 func DirectivesAreDefined() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := directivesAreDefinedVisitor{
@@ -1042,6 +1061,7 @@ func (d *directivesAreDefinedVisitor) EnterDirective(ref int) {
 	}
 }
 
+// DirectivesAreInValidLocations validates if directives are used in the right place
 func DirectivesAreInValidLocations() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := directivesAreInValidLocationsVisitor{
@@ -1090,6 +1110,7 @@ func (d *directivesAreInValidLocationsVisitor) directiveDefinitionContainsNodeLo
 	return d.definition.DirectiveDefinitions[definition].DirectiveLocations.Get(nodeDirectiveLocation)
 }
 
+// VariableUniqueness validates if variables are unique in a given document
 func VariableUniqueness() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := variableUniquenessVisitor{
@@ -1136,6 +1157,7 @@ func (v *variableUniquenessVisitor) EnterVariableDefinition(ref int) {
 	}
 }
 
+// DirectivesAreUniquePerLocation validates if directives are unique per location
 func DirectivesAreUniquePerLocation() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := directivesAreUniquePerLocationVisitor{
@@ -1172,6 +1194,7 @@ func (d *directivesAreUniquePerLocationVisitor) EnterDirective(ref int) {
 	}
 }
 
+// VariablesAreInputTypes validates if variables are correct input types
 func VariablesAreInputTypes() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := variablesAreInputTypesVisitor{
@@ -1206,6 +1229,7 @@ func (v *variablesAreInputTypesVisitor) EnterVariableDefinition(ref int) {
 	}
 }
 
+// AllVariableUsesDefined validates if used variables are defined within the operation
 func AllVariableUsesDefined() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := allVariableUsesDefinedVisitor{
@@ -1252,6 +1276,7 @@ func (a *allVariableUsesDefinedVisitor) EnterArgument(ref int) {
 	a.StopWithExternalErr(operationreport.ErrVariableNotDefinedOnArgument(variableName, argumentName))
 }
 
+// AllVariablesUsed validates if all defined variables are used
 func AllVariablesUsed() Rule {
 	return func(walker *astvisitor.Walker) {
 		visitor := allVariablesUsedVisitor{
diff --git a/pkg/astvisitor/astvisitor.go b/pkg/astvisitor/astvisitor.go
new file mode 100644
index 00000000..49c522c6
--- /dev/null
+++ b/pkg/astvisitor/astvisitor.go
@@ -0,0 +1,8 @@
+// Package astvisitor enables efficient and powerful traversal of GraphQL document AST's.
+//
+// Visitor has more options to configure the behaviour and offers more meta data than SimpleVisitor.
+// SimpleVisitor on the other hand is more performant.
+//
+// If all Nodes should be visited and not much meta data is needed, go with SimpleVisitor.
+// If you only need to visit a subset of Nodes or want specific meta data, e.g. TypeDefinitions you should go with Visitor.
+package astvisitor
diff --git a/pkg/astvisitor/visitor.go b/pkg/astvisitor/visitor.go
index b1912f36..1de18291 100644
--- a/pkg/astvisitor/visitor.go
+++ b/pkg/astvisitor/visitor.go
@@ -14,12 +14,25 @@ var (
 	ErrDefinitionMustNotBeNil = fmt.Errorf("definition must not be nil when walking operations")
 )
 
+// Walker orchestrates the process of walking an AST and calling all registered callbacks
+// Always use NewWalker to instantiate a new Walker
 type Walker struct {
+	// Ancestors is the slice of Nodes to the current Node in a callback
+	// don't keep a reference to this slice, always copy it if you want to work with it after the callback returned
 	Ancestors               []ast.Node
+	// Path is the slice of PathItems leading to the current Node
+	// don't keep a reference to this slice, always copy it if you want to work with it after the callback returned
 	Path                    ast.Path
+	// EnclosingTypeDefinition is the TypeDefinition Node of the parent object of the current callback
+	// e.g. if the current callback is a Field the EnclosingTypeDefinition will be the TypeDefinition of the parent object of such Field
 	EnclosingTypeDefinition ast.Node
+	// SelectionsBefore is the slice of references to selections before the current selection
+	// This is only valid when inside a SelectionSet
 	SelectionsBefore        []int
+	// SelectionsAfter is the slice of references to selections before the current selection
+	// This is only valid when inside a SelectionSet
 	SelectionsAfter         []int
+	// Report is the object to collect errors when walking the AST
 	Report                  *operationreport.Report
 	document                *ast.Document
 	definition              *ast.Document
@@ -31,6 +44,7 @@ type Walker struct {
 	revisit                 bool
 }
 
+// NewWalker returns a fully initialized Walker
 func NewWalker(ancestorSize int) Walker {
 	return Walker{
 		Ancestors:       make([]ast.Node, 0, ancestorSize),
@@ -39,327 +53,518 @@ func NewWalker(ancestorSize int) Walker {
 	}
 }
 
-type Info struct {
-	Depth                     int
-	Ancestors                 []ast.Node
-	SelectionSet              int
-	SelectionsBefore          []int
-	SelectionsAfter           []int
-	ArgumentsBefore           []int
-	ArgumentsAfter            []int
-	VariableDefinitionsBefore []int
-	VariableDefinitionsAfter  []int
-	DirectivesBefore          []int
-	DirectivesAfter           []int
-	InputValueDefinitions     []int
-	HasSelections             bool
-	FieldTypeDefinition       ast.Node
-	EnclosingTypeDefinition   ast.Node
-	IsLastRootNode            bool
-	Definition                ast.Node
-}
-
 type (
+	// EnterOperationDefinitionVisitor is the callback when the walker enters an operation definition
 	EnterOperationDefinitionVisitor interface {
+		// EnterOperationDefinition gets called when the walker enters an operation definition
+		// ref is the reference to the operation definition on the AST
 		EnterOperationDefinition(ref int)
 	}
+	// LeaveOperationDefinitionVisitor is the callback when the walker leaves an operation definition
 	LeaveOperationDefinitionVisitor interface {
+		// LeaveOperationDefinition gets called when the walker leaves an operation definition
+		// ref is the reference to the operation definition on the AST
 		LeaveOperationDefinition(ref int)
 	}
+	// OperationDefinitionVisitor is the callback when the walker enters or leaves an operation
 	OperationDefinitionVisitor interface {
 		EnterOperationDefinitionVisitor
 		LeaveOperationDefinitionVisitor
 	}
+	// EnterSelectionSetVisitor is the callback when the walker enters a selection set
 	EnterSelectionSetVisitor interface {
+		// EnterSelectionSet gets called when the walker enters a selection set
+		// ref is the reference to the selection set on the AST
 		EnterSelectionSet(ref int)
 	}
+	// LeaveSelectionSetVisitor is the callback when the walker leaves a selection set visitor
 	LeaveSelectionSetVisitor interface {
+		// LeaveSelectionSet gets called when the walker leaves a selection set
+		// ref is the reference to the selection set on the AST
 		LeaveSelectionSet(ref int)
 	}
+	// SelectionSetVisitor is the callback when the walker enters or leaves a selection set
 	SelectionSetVisitor interface {
 		EnterSelectionSetVisitor
 		LeaveSelectionSetVisitor
 	}
+	// EnterFieldVisitor is the callback when the walker enters a field
 	EnterFieldVisitor interface {
+		// EnterField gets called when the walker enters a field
+		// ref is the reference to the selection set on the AST
 		EnterField(ref int)
 	}
+	// LeaveFieldVisitor is the callback when the walker leaves a field
 	LeaveFieldVisitor interface {
+		// LeaveField gets called when the walker leaves a field
+		// ref is the reference to the selection set on the AST
 		LeaveField(ref int)
 	}
+	// FieldVisitor is the callback when the walker enters or leaves a field
 	FieldVisitor interface {
 		EnterFieldVisitor
 		LeaveFieldVisitor
 	}
+	// EnterArgumentVisitor is the callback when the walker enters an argument
 	EnterArgumentVisitor interface {
+		// EnterArgument gets called when the walker enters an argument
+		// ref is the reference to the selection set on the AST
 		EnterArgument(ref int)
 	}
+	// LeaveArgumentVisitor is the callback when the walker leaves an argument
 	LeaveArgumentVisitor interface {
+		// LeaveArgument gets called when the walker leaves an argument
+		// ref is the reference to the selection set on the AST
 		LeaveArgument(ref int)
 	}
+	// ArgumentVisitor is the callback when the walker enters or leaves an argument
 	ArgumentVisitor interface {
 		EnterArgumentVisitor
 		LeaveArgumentVisitor
 	}
+	// EnterFragmentSpreadVisitor is the callback when the walker enters a fragment spread
 	EnterFragmentSpreadVisitor interface {
+		// EnterFragmentSpread gets called when the walker enters a fragment spread
+		// ref is the reference to the selection set on the AST
 		EnterFragmentSpread(ref int)
 	}
+	// LeaveFragmentSpreadVisitor is the callback when the walker leaves a fragment spread
 	LeaveFragmentSpreadVisitor interface {
+		// LeaveFragmentSpread gets called when the walker leaves a fragment spread
+		// ref is the reference to the selection set on the AST
 		LeaveFragmentSpread(ref int)
 	}
+	// FragmentSpreadVisitor is the callback when the walker enters or leaves a fragment spread
 	FragmentSpreadVisitor interface {
 		EnterFragmentSpreadVisitor
 		LeaveFragmentSpreadVisitor
 	}
+	// EnterFragmentSpreadVisitor is the callback when the walker enters an inline framgnet
 	EnterInlineFragmentVisitor interface {
+		// EnterInlineFragment gets called when the walker enters an inline fragment
+		// ref is the reference to the selection set on the AST
 		EnterInlineFragment(ref int)
 	}
+	// LeaveInlineFragmentVisitor is the callback when the walker leaves an inline fragment
 	LeaveInlineFragmentVisitor interface {
+		// LeaveInlineFragment gets called when the walker leaves an inline fragment
+		// ref is the reference to the selection set on the AST
 		LeaveInlineFragment(ref int)
 	}
+	// InlineFragmentVisitor is the callback when the walker enters or leaves an inline fragment
 	InlineFragmentVisitor interface {
 		EnterInlineFragmentVisitor
 		LeaveInlineFragmentVisitor
 	}
+	// EnterFragmentDefinitionVisitor is the callback when the walker enters a fragment definition
 	EnterFragmentDefinitionVisitor interface {
+		// EnterFragmentDefinition gets called when the walker enters a fragment definition
+		// ref is the reference to the selection set on the AST
 		EnterFragmentDefinition(ref int)
 	}
+	// LeaveFragmentDefinitionVisitor is the callback when the walker leaves a fragment definition
 	LeaveFragmentDefinitionVisitor interface {
+		// LeaveFragmentDefinition gets called when the walker leaves a fragment definition
+		// ref is the reference to the selection set on the AST
 		LeaveFragmentDefinition(ref int)
 	}
+	// FragmentDefinitionVisitor is the callback when the walker enters or leaves a fragment definition
 	FragmentDefinitionVisitor interface {
 		EnterFragmentDefinitionVisitor
 		LeaveFragmentDefinitionVisitor
 	}
+	// EnterFragmentDefinitionVisitor is the callback when the walker enters a variable definition
 	EnterVariableDefinitionVisitor interface {
+		// EnterVariableDefinition gets called when the walker enters a variable definition
+		// ref is the reference to the selection set on the AST
 		EnterVariableDefinition(ref int)
 	}
+	// LeaveVariableDefinitionVisitor is the callback when the walker leaves a variable definition
 	LeaveVariableDefinitionVisitor interface {
+		// LeaveVariableDefinition gets called when the walker leaves a variable definition
+		// ref is the reference to the selection set on the AST
 		LeaveVariableDefinition(ref int)
 	}
+	// VariableDefinitionVisitor is the callback when the walker enters or leaves a variable definition
 	VariableDefinitionVisitor interface {
 		EnterVariableDefinitionVisitor
 		LeaveVariableDefinitionVisitor
 	}
+	// EnterDirectiveVisitor is the callback when the walker enters a directive
 	EnterDirectiveVisitor interface {
+		// EnterDirective gets called when the walker enters a directive
+		// ref is the reference to the selection set on the AST
 		EnterDirective(ref int)
 	}
+	// LeaveDirectiveVisitor is the callback when the walker leaves a directive
 	LeaveDirectiveVisitor interface {
+		// LeaveDirective gets called when the walker leaves a directive
+		// ref is the reference to the selection set on the AST
 		LeaveDirective(ref int)
 	}
+	// DirectiveVisitor is the callback when the walker enters or leaves a directive
 	DirectiveVisitor interface {
 		EnterDirectiveVisitor
 		LeaveDirectiveVisitor
 	}
+	// EnterObjectTypeDefinitionVisitor is the callback when the walker enters an object type definition
 	EnterObjectTypeDefinitionVisitor interface {
+		// EnterObjectTypeDefinition gets called when the walker enters an object type definition
+		// ref is the reference to the selection set on the AST
 		EnterObjectTypeDefinition(ref int)
 	}
+	// LeaveObjectTypeDefinitionVisitor is the callback when the walker leaves an object type definition
 	LeaveObjectTypeDefinitionVisitor interface {
+		// LeaveObjectTypeDefinition gets called when the walker leaves an object type definition
+		// ref is the reference to the selection set on the AST
 		LeaveObjectTypeDefinition(ref int)
 	}
+	// ObjectTypeDefinitionVisitor is the callback when the walker enters or leaves an object type definition
 	ObjectTypeDefinitionVisitor interface {
 		EnterObjectTypeDefinitionVisitor
 		LeaveObjectTypeDefinitionVisitor
 	}
+	// EnterObjectTypeExtensionVisitor is the callback when the walker enters an object type extension
 	EnterObjectTypeExtensionVisitor interface {
+		// EnterObjectTypeExtension gets called when the walker enters an object type extension
+		// ref is the reference to the selection set on the AST
 		EnterObjectTypeExtension(ref int)
 	}
+	// LeaveObjectTypeExtensionVisitor is the callback when the walker leaves an object type extension
 	LeaveObjectTypeExtensionVisitor interface {
+		// LeaveObjectTypeExtension gets called when the walker leaves an object type extension
+		// ref is the reference to the selection set on the AST
 		LeaveObjectTypeExtension(ref int)
 	}
+	// ObjectTypeExtensionVisitor is the callback when the walker enters or leaves an object type extension
 	ObjectTypeExtensionVisitor interface {
 		EnterObjectTypeExtensionVisitor
 		LeaveObjectTypeExtensionVisitor
 	}
+	// EnterFieldDefinitionVisitor is the callback when the walker enters a field definition
 	EnterFieldDefinitionVisitor interface {
+		// EnterFieldDefinition gets called when the walker enters a field definition
+		// ref is the reference to the selection set on the AST
 		EnterFieldDefinition(ref int)
 	}
+	// LeaveFieldDefinitionVisitor is the callback when the walker leaves a field definition
 	LeaveFieldDefinitionVisitor interface {
+		// LeaveFieldDefinition gets called when the walker leaves a field definition
+		// ref is the reference to the selection set on the AST
 		LeaveFieldDefinition(ref int)
 	}
+	// FieldDefinitionVisitor is the callback when the walker enters or leaves a field definition
 	FieldDefinitionVisitor interface {
 		EnterFieldDefinitionVisitor
 		LeaveFieldDefinitionVisitor
 	}
+	// EnterInputValueDefinitionVisitor is the callback when the walker enters an input value definition
 	EnterInputValueDefinitionVisitor interface {
+		// EnterInputValueDefinition gets called when the walker enters an input value definition
+		// ref is the reference to the selection set on the AST
 		EnterInputValueDefinition(ref int)
 	}
+	// LeaveInputValueDefinitionVisitor is the callback when the walker leaves an input value definition
 	LeaveInputValueDefinitionVisitor interface {
+		// LeaveInputValueDefinition gets called when the walker leaves an input value definition
+		// ref is the reference to the selection set on the AST
 		LeaveInputValueDefinition(ref int)
 	}
+	// InputValueDefinitionVisitor is the callback when the walker enters or leaves an input value definition
 	InputValueDefinitionVisitor interface {
 		EnterInputValueDefinitionVisitor
 		LeaveInputValueDefinitionVisitor
 	}
+	// EnterInterfaceTypeDefinitionVisitor is the callback when the walker enters an interface type definition
 	EnterInterfaceTypeDefinitionVisitor interface {
+		// EnterInterfaceTypeDefinition gets called when the walker enters an interface type definition
+		// ref is the reference to the selection set on the AST
 		EnterInterfaceTypeDefinition(ref int)
 	}
+	// LeaveInterfaceTypeDefinitionVisitor is the callback when the walker leaves an interface type definition
 	LeaveInterfaceTypeDefinitionVisitor interface {
+		// LeaveInterfaceTypeDefinition gets called when the walker leaves an interface type definition
+		// ref is the reference to the selection set on the AST
 		LeaveInterfaceTypeDefinition(ref int)
 	}
+	// InterfaceTypeDefinitionVisitor is the callback when the walker enters or leaves an interface type definition
 	InterfaceTypeDefinitionVisitor interface {
 		EnterInterfaceTypeDefinitionVisitor
 		LeaveInterfaceTypeDefinitionVisitor
 	}
+	// EnterInterfaceTypeExtensionVisitor is the callback when the walker enters an interface type extension
 	EnterInterfaceTypeExtensionVisitor interface {
+		// EnterInterfaceTypeExtension gets called when the walker enters an interface type extension
+		// ref is the reference to the selection set on the AST
 		EnterInterfaceTypeExtension(ref int)
 	}
+	// LeaveInterfaceTypeExtensionVisitor is the callback when the walker leaves an interface type extension
 	LeaveInterfaceTypeExtensionVisitor interface {
+		// LeaveInterfaceTypeExtension gets called when the walker leaves an interface type extension
+		// ref is the reference to the selection set on the AST
 		LeaveInterfaceTypeExtension(ref int)
 	}
+	// InterfaceTypeExtensionVisitor is the callback when the walker enters or leaves an interface type extension
 	InterfaceTypeExtensionVisitor interface {
 		EnterInterfaceTypeExtensionVisitor
 		LeaveInterfaceTypeExtensionVisitor
 	}
+	// EnterScalarTypeDefinitionVisitor is the callback when the walker enters a scalar type definition
 	EnterScalarTypeDefinitionVisitor interface {
+		// EnterScalarTypeDefinition gets called when the walker enters a scalar type definition
+		// ref is the reference to the selection set on the AST
 		EnterScalarTypeDefinition(ref int)
 	}
+	// LeaveScalarTypeDefinitionVisitor is the callback when the walker leaves a scalar type definition
 	LeaveScalarTypeDefinitionVisitor interface {
+		// LeaveScalarTypeDefinition gets called when the walker leaves a scalar type definition
+		// ref is the reference to the selection set on the AST
 		LeaveScalarTypeDefinition(ref int)
 	}
+	// ScalarTypeDefinitionVisitor is the callback when the walker enters or leaves a scalar type definition
 	ScalarTypeDefinitionVisitor interface {
 		EnterScalarTypeDefinitionVisitor
 		LeaveScalarTypeDefinitionVisitor
 	}
+	// EnterScalarTypeExtensionVisitor is the callback when the walker enters a scalar type extension
 	EnterScalarTypeExtensionVisitor interface {
+		// EnterScalarTypeExtension gets called when the walker enters a scalar type extension
+		// ref is the reference to the selection set on the AST
 		EnterScalarTypeExtension(ref int)
 	}
+	// LeaveScalarTypeExtensionVisitor is the callback when the walker leaves a scalar type extension
 	LeaveScalarTypeExtensionVisitor interface {
+		// LeaveScalarTypeExtension gets called when the walker leaves a scalar type extension
+		// ref is the reference to the selection set on the AST
 		LeaveScalarTypeExtension(ref int)
 	}
+	// ScalarTypeExtensionVisitor is the callback when the walker enters or leaves a scalar type extension
 	ScalarTypeExtensionVisitor interface {
 		EnterScalarTypeExtensionVisitor
 		LeaveScalarTypeExtensionVisitor
 	}
+	// EnterUnionTypeDefinitionVisitor is the callback when the walker enters a union type definition
 	EnterUnionTypeDefinitionVisitor interface {
+		// EnterUnionTypeDefinition gets called when the walker enters a union type definition
+		// ref is the reference to the selection set on the AST
 		EnterUnionTypeDefinition(ref int)
 	}
+	// LeaveUnionTypeDefinitionVisitor is the callback when the walker leaves a union type definition
 	LeaveUnionTypeDefinitionVisitor interface {
+		// LeaveUnionTypeDefinition gets called when the walker leaves a union type definition
+		// ref is the reference to the selection set on the AST
 		LeaveUnionTypeDefinition(ref int)
 	}
+	// UnionTypeDefinitionVisitor is the callback when the walker enters or leaves a union type definition
 	UnionTypeDefinitionVisitor interface {
 		EnterUnionTypeDefinitionVisitor
 		LeaveUnionTypeDefinitionVisitor
 	}
+	// EnterUnionTypeExtensionVisitor is the callback when the walker enters a union type extension
 	EnterUnionTypeExtensionVisitor interface {
+		// EnterUnionTypeExtension gets called when the walker enters a union type extension
+		// ref is the reference to the selection set on the AST
 		EnterUnionTypeExtension(ref int)
 	}
+	// LeaveUnionTypeExtensionVisitor is the callback when the walker leaves a union type extension
 	LeaveUnionTypeExtensionVisitor interface {
+		// LeaveUnionTypeExtension gets called when the walker leaves a union type extension
+		// ref is the reference to the selection set on the AST
 		LeaveUnionTypeExtension(ref int)
 	}
+	// UnionTypeExtensionVisitor is the callback when the walker enters or leaves a union type extension
 	UnionTypeExtensionVisitor interface {
 		EnterUnionTypeExtensionVisitor
 		LeaveUnionTypeExtensionVisitor
 	}
+	// EnterUnionMemberTypeVisitor is the callback when the walker enters a union member type
 	EnterUnionMemberTypeVisitor interface {
+		// EnterUnionMemberType gets called when the walker enters a union member type
+		// ref is the reference to the selection set on the AST
 		EnterUnionMemberType(ref int)
 	}
+	// LeaveUnionMemberTypeVisitor is the callback when the walker leaves a union member type
 	LeaveUnionMemberTypeVisitor interface {
+		// LeaveUnionMemberType gets called when the walker leaves a union member type
+		// ref is the reference to the selection set on the AST
 		LeaveUnionMemberType(ref int)
 	}
+	// UnionMemberTypeVisitor is the callback when the walker enters or leaves a union member type
 	UnionMemberTypeVisitor interface {
 		EnterUnionMemberTypeVisitor
 		LeaveUnionMemberTypeVisitor
 	}
+	// EnterEnumTypeDefinitionVisitor is the callback when the walker enters an enum type definition
 	EnterEnumTypeDefinitionVisitor interface {
+		// EnterEnumTypeDefinition gets called when the walker enters an enum type definition
+		// ref is the reference to the selection set on the AST
 		EnterEnumTypeDefinition(ref int)
 	}
+	// LeaveEnumTypeDefinitionVisitor is the callback when the walker leaves an enum type definition
 	LeaveEnumTypeDefinitionVisitor interface {
+		// LeaveEnumTypeDefinition gets called when the walker leaves an enum type definition
+		// ref is the reference to the selection set on the AST
 		LeaveEnumTypeDefinition(ref int)
 	}
+	// EnumTypeDefinitionVisitor is the callback when the walker enters or leaves an enum type definition
 	EnumTypeDefinitionVisitor interface {
 		EnterEnumTypeDefinitionVisitor
 		LeaveEnumTypeDefinitionVisitor
 	}
+	// EnterEnumTypeExtensionVisitor is the callback when the walker enters an enum type extension
 	EnterEnumTypeExtensionVisitor interface {
+		// EnterEnumTypeExtension gets called when the walker enters an enum type extension
+		// ref is the reference to the selection set on the AST
 		EnterEnumTypeExtension(ref int)
 	}
+	// LeaveEnumTypeExtensionVisitor is the callback when the walker leaves an enum type extension
 	LeaveEnumTypeExtensionVisitor interface {
+		// LeaveEnumTypeExtension gets called when the walker leaves an enum type extension
+		// ref is the reference to the selection set on the AST
 		LeaveEnumTypeExtension(ref int)
 	}
+	// EnumTypeExtensionVisitor is the callback when the walker enters or leaves an enum type extension
 	EnumTypeExtensionVisitor interface {
 		EnterEnumTypeExtensionVisitor
 		LeaveEnumTypeExtensionVisitor
 	}
+	// EnterEnumValueDefinitionVisitor is the callback when the walker enters an enum value definition
 	EnterEnumValueDefinitionVisitor interface {
+		// EnterEnumValueDefinition gets called when the walker enters an enum value definition
+		// ref is the reference to the selection set on the AST
 		EnterEnumValueDefinition(ref int)
 	}
+	// LeaveEnumValueDefinitionVisitor is the callback when the walker leaves an enum value definition
 	LeaveEnumValueDefinitionVisitor interface {
+		// LeaveEnumValueDefinition gets called when the walker leaves an enum value definition
+		// ref is the reference to the selection set on the AST
 		LeaveEnumValueDefinition(ref int)
 	}
+	// EnumValueDefinitionVisitor is the callback when the walker enters or leaves an enum value definition
 	EnumValueDefinitionVisitor interface {
 		EnterEnumValueDefinitionVisitor
 		LeaveEnumValueDefinitionVisitor
 	}
+	// EnterInputObjectTypeDefinitionVisitor is the callback when the walker enters an input object type definition
 	EnterInputObjectTypeDefinitionVisitor interface {
+		// EnterInputObjectTypeDefinition gets called when the walker enters an input object type definition
+		// ref is the reference to the selection set on the AST
 		EnterInputObjectTypeDefinition(ref int)
 	}
+	// LeaveInputObjectTypeDefinitionVisitor is the callback when the walker leaves an input object type definition
 	LeaveInputObjectTypeDefinitionVisitor interface {
+		// LeaveInputObjectTypeDefinition gets called when the walker leaves an input object type definition
+		// ref is the reference to the selection set on the AST
 		LeaveInputObjectTypeDefinition(ref int)
 	}
+	// InputObjectTypeDefinitionVisitor is the callback when the walker enters or leaves an input object type definition
 	InputObjectTypeDefinitionVisitor interface {
 		EnterInputObjectTypeDefinitionVisitor
 		LeaveInputObjectTypeDefinitionVisitor
 	}
+	// EnterInputObjectTypeExtensionVisitor is the callback when the walker enters an input object type extension
 	EnterInputObjectTypeExtensionVisitor interface {
+		// EnterInputObjectTypeExtension gets called when the walker enters an input object type extension
+		// ref is the reference to the selection set on the AST
 		EnterInputObjectTypeExtension(ref int)
 	}
+	// LeaveInputObjectTypeExtensionVisitor is the callback when the walker leaves an input object type extension
 	LeaveInputObjectTypeExtensionVisitor interface {
+		// LeaveInputObjectTypeExtension gets called when the walker leaves an input object type extension
+		// ref is the reference to the selection set on the AST
 		LeaveInputObjectTypeExtension(ref int)
 	}
+	// InputObjectTypeExtensionVisitor is the callback when the walker enters or leaves an input object type extension
 	InputObjectTypeExtensionVisitor interface {
 		EnterInputObjectTypeExtensionVisitor
 		LeaveInputObjectTypeExtensionVisitor
 	}
+	// EnterDirectiveDefinitionVisitor is the callback when the walker enters a directive definition
 	EnterDirectiveDefinitionVisitor interface {
+		// EnterDirectiveDefinition gets called when the walker enters a directive definition
+		// ref is the reference to the selection set on the AST
 		EnterDirectiveDefinition(ref int)
 	}
+	// LeaveDirectiveDefinitionVisitor is the callback when the walker leaves a directive definition
 	LeaveDirectiveDefinitionVisitor interface {
+		// LeaveDirectiveDefinition gets called when the walker leaves a directive definition
+		// ref is the reference to the selection set on the AST
 		LeaveDirectiveDefinition(ref int)
 	}
+	// DirectiveDefinitionVisitor is the callback when the walker enters or leaves a directive definition
 	DirectiveDefinitionVisitor interface {
 		EnterDirectiveDefinitionVisitor
 		LeaveDirectiveDefinitionVisitor
 	}
+	// EnterDirectiveLocationVisitor is the callback when the walker enters a directive location
 	EnterDirectiveLocationVisitor interface {
+		// EnterDirectiveLocation gets called when the walker enters a directive location
+		// ref is the reference to the selection set on the AST
 		EnterDirectiveLocation(location ast.DirectiveLocation)
 	}
+	// LeaveDirectiveLocationVisitor is the callback when the walker leaves a directive location
 	LeaveDirectiveLocationVisitor interface {
+		// LeaveDirectiveLocation gets called when the walker leaves a directive location
+		// ref is the reference to the selection set on the AST
 		LeaveDirectiveLocation(location ast.DirectiveLocation)
 	}
+	// DirectiveLocationVisitor is the callback when the walker enters or leaves a directive location
 	DirectiveLocationVisitor interface {
 		EnterDirectiveLocationVisitor
 		LeaveDirectiveLocationVisitor
 	}
+	// EnterSchemaDefinitionVisitor is the callback when the walker enters a schema definition
 	EnterSchemaDefinitionVisitor interface {
+		// EnterSchemaDefinition gets called when the walker enters a schema definition
+		// ref is the reference to the selection set on the AST
 		EnterSchemaDefinition(ref int)
 	}
+	// LeaveSchemaDefinitionVisitor is the callback when the walker leaves a schema definition
 	LeaveSchemaDefinitionVisitor interface {
+		// LeaveSchemaDefinition gets called when the walker leaves a schema definition
+		// ref is the reference to the selection set on the AST
 		LeaveSchemaDefinition(ref int)
 	}
+	// SchemaDefinitionVisitor is the callback when the walker enters or leaves a schema definition
 	SchemaDefinitionVisitor interface {
 		EnterSchemaDefinitionVisitor
 		LeaveSchemaDefinitionVisitor
 	}
+	// EnterSchemaExtensionVisitor is the callback when the walker enters a schema extension
 	EnterSchemaExtensionVisitor interface {
+		// EnterSchemaExtension gets called when the walker enters a schema extension
+		// ref is the reference to the selection set on the AST
 		EnterSchemaExtension(ref int)
 	}
+	// LeaveSchemaExtensionVisitor is the callback when the walker leaves a schema extension
 	LeaveSchemaExtensionVisitor interface {
+		// LeaveSchemaExtension gets called when the walker leaves a schema extension
+		// ref is the reference to the selection set on the AST
 		LeaveSchemaExtension(ref int)
 	}
+	// SchemaExtensionVisitor is the callback when the walker enters or leaves a schema extension
 	SchemaExtensionVisitor interface {
 		EnterSchemaExtensionVisitor
 		LeaveSchemaExtensionVisitor
 	}
+	// EnterRootOperationTypeDefinitionVisitor is the callback when the walker enters a root operation type definition
 	EnterRootOperationTypeDefinitionVisitor interface {
+		// EnterRootOperationTypeDefinition gets called when the walker enters a root operation type definition
+		// ref is the reference to the selection set on the AST
 		EnterRootOperationTypeDefinition(ref int)
 	}
+	// LeaveRootOperationTypeDefinitionVisitor is the callback when the walker leaves a root operation type definition
 	LeaveRootOperationTypeDefinitionVisitor interface {
+		// LeaveRootOperationTypeDefinition gets called when the walker leaves a root operation type definition
+		// ref is the reference to the selection set on the AST
 		LeaveRootOperationTypeDefinition(ref int)
 	}
+	// RootOperationTypeDefinitionVisitor is the callback when the walker enters or leaves a root operation type definition
 	RootOperationTypeDefinitionVisitor interface {
 		EnterRootOperationTypeDefinitionVisitor
 		LeaveRootOperationTypeDefinitionVisitor
 	}
+	// TypeSystemVisitor is the callback when the walker enters or leaves any of the type definitions
 	TypeSystemVisitor interface {
 		ObjectTypeDefinitionVisitor
 		ObjectTypeExtensionVisitor
@@ -383,6 +588,7 @@ type (
 		SchemaExtensionVisitor
 		RootOperationTypeDefinitionVisitor
 	}
+	// ExecutableVisitor is the callback when the walker enters or leaves any of the executable definitions
 	ExecutableVisitor interface {
 		OperationDefinitionVisitor
 		SelectionSetVisitor
@@ -394,16 +600,21 @@ type (
 		VariableDefinitionVisitor
 		DirectiveVisitor
 	}
+	// EnterDocumentVisitor is the callback when the walker enters a document
 	EnterDocumentVisitor interface {
+		// EnterDocument gets called when the walker enters a document
 		EnterDocument(operation, definition *ast.Document)
 	}
 	LeaveDocumentVisitor interface {
+		// LeaveDocument gets called when the walker leaves a document
 		LeaveDocument(operation, definition *ast.Document)
 	}
+	// DocumentVisitor is the callback when the walker enters or leaves a document
 	DocumentVisitor interface {
 		EnterDocumentVisitor
 		LeaveDocumentVisitor
 	}
+	// AllNodesVisitor is the callback when the walker enters or leaves any Node
 	AllNodesVisitor interface {
 		DocumentVisitor
 		TypeSystemVisitor
@@ -476,6 +687,7 @@ type visitors struct {
 	leaveRootOperationTypeDefinition []LeaveRootOperationTypeDefinitionVisitor
 }
 
+// ResetVisitors empties all registered visitors / unregisters all callbacks
 func (w *Walker) ResetVisitors() {
 	w.visitors.enterOperation = w.visitors.enterOperation[:0]
 	w.visitors.leaveOperation = w.visitors.leaveOperation[:0]
@@ -986,6 +1198,7 @@ func (w *Walker) RegisterDocumentVisitor(visitor DocumentVisitor) {
 	w.RegisterLeaveDocumentVisitor(visitor)
 }
 
+// Walk initiates the walker to start walking the AST from the top root Node
 func (w *Walker) Walk(document, definition *ast.Document, report *operationreport.Report) {
 	if report == nil {
 		w.Report = &operationreport.Report{}
diff --git a/pkg/escape/escape.go b/pkg/escape/escape.go
new file mode 100644
index 00000000..25830879
--- /dev/null
+++ b/pkg/escape/escape.go
@@ -0,0 +1,2 @@
+// Package escape enables efficient JSON escaping on byte slices.
+package escape
diff --git a/pkg/execution/execution.go b/pkg/execution/execution.go
index 8f9b4d84..a694f2d4 100644
--- a/pkg/execution/execution.go
+++ b/pkg/execution/execution.go
@@ -1,3 +1,5 @@
+// Package execution is a complete GraphQL runtime.
+// It contains a Handler to orchestrate the execution, a Query Planner to generate a Query Plan from an AST as well as the Executor to execute a Query Plan.
 package execution
 
 import (
diff --git a/pkg/http/http.go b/pkg/http/http.go
index db43d7d3..786dc989 100644
--- a/pkg/http/http.go
+++ b/pkg/http/http.go
@@ -1,3 +1,4 @@
+// Package http handles GraphQL HTTP Requests including WebSocket Upgrades.
 package http
 
 import (
diff --git a/pkg/imports/imports.go b/pkg/imports/imports.go
index a8c5ef02..1ace8dc2 100644
--- a/pkg/imports/imports.go
+++ b/pkg/imports/imports.go
@@ -1,3 +1,4 @@
+// Package imports helps combining multiple GraphQL documents into one document using import comments.
 package imports
 
 import (
diff --git a/pkg/introspection/introspection.go b/pkg/introspection/introspection.go
index f8476615..86af8df5 100644
--- a/pkg/introspection/introspection.go
+++ b/pkg/introspection/introspection.go
@@ -1,5 +1,6 @@
 //go:generate go-enum -f=$GOFILE --noprefix --marshal
 
+// Package introspection takes a GraphQL Schema and provides the introspection JSON to fulfill introspection queries.
 package introspection
 
 import (
diff --git a/pkg/lexer/identkeyword/identkeyword.go b/pkg/lexer/identkeyword/identkeyword.go
index 0e42363f..57bdcf28 100644
--- a/pkg/lexer/identkeyword/identkeyword.go
+++ b/pkg/lexer/identkeyword/identkeyword.go
@@ -1,4 +1,6 @@
 //go:generate stringer -type=IdentKeyword
+
+// Package identkeyword contains all possible keywords for GraphQL identifiers
 package identkeyword
 
 type IdentKeyword int
diff --git a/pkg/lexer/keyword/keyword.go b/pkg/lexer/keyword/keyword.go
index a9b8b4c9..bfaf5356 100644
--- a/pkg/lexer/keyword/keyword.go
+++ b/pkg/lexer/keyword/keyword.go
@@ -1,4 +1,6 @@
 //go:generate stringer -type=Keyword
+
+// Package keyword contains all possible GraphQL keywords
 package keyword
 
 type Keyword int
diff --git a/pkg/lexer/lexer.go b/pkg/lexer/lexer.go
index 55be5437..157aeced 100644
--- a/pkg/lexer/lexer.go
+++ b/pkg/lexer/lexer.go
@@ -1,3 +1,4 @@
+// Package lexer contains the logic to turn an ast.Input into lexed tokens
 package lexer
 
 import (
diff --git a/pkg/lexer/literal/literal.go b/pkg/lexer/literal/literal.go
index cb49f711..7e2ed24c 100644
--- a/pkg/lexer/literal/literal.go
+++ b/pkg/lexer/literal/literal.go
@@ -1,3 +1,4 @@
+// Package literal contains a selection of frequently used literals with GraphQL APIs
 package literal
 
 import "bytes"
diff --git a/pkg/lexer/position/position.go b/pkg/lexer/position/position.go
index 979493eb..e21fdc8c 100644
--- a/pkg/lexer/position/position.go
+++ b/pkg/lexer/position/position.go
@@ -1,3 +1,4 @@
+// Package position contains the objects and logic to properly describe the position of a token in a GraphQL document
 package position
 
 import "fmt"
diff --git a/pkg/lexer/runes/runes.go b/pkg/lexer/runes/runes.go
index 18befb5a..54ac745a 100644
--- a/pkg/lexer/runes/runes.go
+++ b/pkg/lexer/runes/runes.go
@@ -1,3 +1,4 @@
+// Package runes contains all possible 'special' runes in a GraphQL document
 package runes
 
 const (
diff --git a/pkg/lexer/token/token.go b/pkg/lexer/token/token.go
index b4d17838..ec25f7cb 100644
--- a/pkg/lexer/token/token.go
+++ b/pkg/lexer/token/token.go
@@ -1,3 +1,4 @@
+// Package token contains the object and logic needed to describe a lexed token in a GraphQL document
 package token
 
 import (
diff --git a/pkg/middleware/middleware.go b/pkg/middleware/middleware.go
new file mode 100644
index 00000000..2c1bd401
--- /dev/null
+++ b/pkg/middleware/middleware.go
@@ -0,0 +1,2 @@
+// Package middleware contains useful middleware components for GraphQL services, e.g. for complexity analysis.
+package middleware
diff --git a/pkg/operationreport/report.go b/pkg/operationreport/operationreport.go
similarity index 91%
rename from pkg/operationreport/report.go
rename to pkg/operationreport/operationreport.go
index cbf25d89..1def2974 100644
--- a/pkg/operationreport/report.go
+++ b/pkg/operationreport/operationreport.go
@@ -1,3 +1,4 @@
+// Package operationreport helps generating the errors object for a GraphQL Operation.
 package operationreport
 
 import "fmt"
diff --git a/pkg/playground/playground.go b/pkg/playground/playground.go
index 03afe810..d9f7acf9 100644
--- a/pkg/playground/playground.go
+++ b/pkg/playground/playground.go
@@ -1,4 +1,6 @@
 //go:generate packr
+
+// Package playground is a http.Handler hosting the GraphQL Playground application.
 package playground
 
 import (


Test patch:
diff --git a/pkg/ast/ast_test.go b/pkg/ast/ast_test.go
new file mode 100644
index 00000000..0811e5ad
--- /dev/null
+++ b/pkg/ast/ast_test.go
@@ -0,0 +1,125 @@
+package ast
+
+// Create a new document with initialized slices.
+// In case you're on a hot path you always want to use a pre-initialized Document.
+func ExampleNewDocument() {
+
+	schema := []byte(`
+		schema {
+			query: Query
+		}
+		
+		type Query {
+			hello: String!
+		}
+	`)
+
+	doc := NewDocument()
+	doc.Input.ResetInputBytes(schema)
+
+	// ...then parse the Input
+}
+
+// Create a new Document without pre-initializing slices.
+// Use this if you want to manually create a new Document
+func ExampleDocument() {
+
+	// create the same doc as in NewDocument() example but manually.
+
+	doc := &Document{}
+
+	// add Query to the raw input
+	queryTypeName := doc.Input.AppendInputString("Query")
+
+	// create a RootOperationTypeDefinition
+	rootOperationTypeDefinition := RootOperationTypeDefinition{
+		OperationType: OperationTypeQuery,
+		NamedType: Type{
+			Name: queryTypeName,
+		},
+	}
+
+	// add the RootOperationTypeDefinition to the ast
+	doc.RootOperationTypeDefinitions = append(doc.RootOperationTypeDefinitions, rootOperationTypeDefinition)
+	// get a reference to the RootOperationTypeDefinition
+	queryRootOperationTypeRef := len(doc.RootOperationTypeDefinitions) - 1
+
+	// create a SchemaDefinition
+	schemaDefinition := SchemaDefinition{
+		RootOperationTypeDefinitions: RootOperationTypeDefinitionList{
+			// add the RootOperationTypeDefinition reference
+			Refs: []int{queryRootOperationTypeRef},
+		},
+	}
+
+	// add the SchemaDefinition to the ast
+	doc.SchemaDefinitions = append(doc.SchemaDefinitions, schemaDefinition)
+	// get a reference to the SchemaDefinition
+	schemaDefinitionRef := len(doc.SchemaDefinitions) - 1
+
+	// add the SchemaDefinition to the RootNodes
+	// all root level nodes have to be added to the RootNodes slice in order to make them available to the Walker for traversal
+	doc.RootNodes = append(doc.RootNodes, Node{Kind: NodeKindSchemaDefinition, Ref: schemaDefinitionRef})
+
+	// add another string to the raw input
+	stringName := doc.Input.AppendInputString("String")
+
+	// create a named Type
+	stringType := Type{
+		TypeKind:TypeKindNamed,
+		Name: stringName,
+	}
+
+	// add the Type to the ast
+	doc.Types = append(doc.Types,stringType)
+	// get a reference to the Type
+	stringTypeRef := len(doc.Types) -1
+
+	// create another Type
+	nonNullStringType := Type{
+		TypeKind:TypeKindNonNull,
+		// add a reference to the named type
+		OfType:stringTypeRef,
+	}
+	// Result: NonNull String / String!
+
+	// add the Type to the ast
+	doc.Types = append(doc.Types,nonNullStringType)
+	// get a reference to the Type
+	nonNullStringTypeRef := len(doc.Types) -1
+
+	// add another string to the raw input
+	helloName := doc.Input.AppendInputString("hello")
+
+	// create a FieldDefinition
+	helloFieldDefinition := FieldDefinition{
+		Name: helloName,
+		// add the Type reference
+		Type: nonNullStringTypeRef,
+	}
+
+	// add the FieldDefinition to the ast
+	doc.FieldDefinitions = append(doc.FieldDefinitions,helloFieldDefinition)
+	// get a reference to the FieldDefinition
+	helloFieldDefinitionRef := len(doc.FieldDefinitions)-1
+
+	// create an ObjectTypeDefinition
+	queryTypeDefinition := ObjectTypeDefinition{
+		Name:                queryTypeName,
+		// declare that this ObjectTypeDefinition has fields
+		// this is necessary for the Walker to understand it must walk FieldDefinitions
+		HasFieldDefinitions: true,
+		FieldsDefinition: FieldDefinitionList{
+			// add the FieldDefinition reference
+			Refs: []int{helloFieldDefinitionRef},
+		},
+	}
+
+	// add ObjectTypeDefinition to the ast
+	doc.ObjectTypeDefinitions = append(doc.ObjectTypeDefinitions, queryTypeDefinition)
+	// get reference to ObjectTypeDefinition
+	queryTypeRef := len(doc.ObjectTypeDefinitions) - 1
+
+	// add ObjectTypeDefinition to the RootNodes
+	doc.RootNodes = append(doc.RootNodes, Node{Kind: NodeKindObjectTypeDefinition, Ref: queryTypeRef})
+}
diff --git a/pkg/astimport/astimport_test.go b/pkg/astimport/astimport_test.go
index 62b02580..0df77226 100644
--- a/pkg/astimport/astimport_test.go
+++ b/pkg/astimport/astimport_test.go
@@ -2,6 +2,7 @@ package astimport
 
 import (
 	"bytes"
+	"fmt"
 	"github.com/jensneuse/graphql-go-tools/pkg/ast"
 	"testing"
 )
@@ -29,4 +30,22 @@ func TestImporter_ImportType(t *testing.T) {
 			t.Fatalf("want: {{%s}}\ngot: {{%s}}'",string(typeBytes),string(out))
 		}
 	}
+}
+
+func ExampleImporter_ImportType() {
+	typeBytes := []byte("String!")
+	doc := ast.Document{}
+	importer := NewImporter()
+
+	ref := importer.ImportType(typeBytes,&doc)
+	// reference to the type
+	fmt.Println(ref)
+	// reference to the nested type
+	fmt.Println(doc.Types[ref].OfType)
+	// name of the nested type
+	fmt.Println(doc.TypeNameString(doc.Types[ref].OfType))
+	// Output:
+	// 1
+	// 0
+	// String
 }
\ No newline at end of file