You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: schema.go
    path of file: ./repos/gotosocial/vendor/github.com/go-swagger/go-swagger/codescan
    
    the code of the file until where you have to start completion: package codescan

import (
	"encoding/json"
	"fmt"
	"go/ast"
	"go/importer"
	"go/types"
	"log"
	"os"
	"reflect"
	"strconv"
	"strings"

	"golang.org/x/tools/go/ast/astutil"

	"github.com/go-openapi/spec"
	"github.com/pkg/errors"
)

func addExtension(ve *spec.VendorExtensible, key string, value interface{}) {
	if os.Getenv("SWAGGER_GENERATE_EXTENSION") == "false" {
		return
	}

	ve.AddExtension(key, value)
}

type schemaTypable struct {
	schema *spec.Schema
	level  int
}

func (st schemaTypable) Typed(tpe, format string) {
	st.schema.Typed(tpe, format)
}

func (st schemaTypable) SetRef(ref spec.Ref) {
	st.schema.Ref = ref
}

func (st schemaTypable) Schema() *spec.Schema {
	return st.schema
}

func (st schemaTypable) Items() swaggerTypable {
	if st.schema.Items == nil {
		st.schema.Items = new(spec.SchemaOrArray)
	}
	if st.schema.Items.Schema == nil {
		st.schema.Items.Schema = new(spec.Schema)
	}

	st.schema.Typed("array", "")
	return schemaTypable{st.schema.Items.Schema, st.level + 1}
}

func (st schemaTypable) AdditionalProperties() swaggerTypable {
	if st.schema.AdditionalProperties == nil {
		st.schema.AdditionalProperties = new(spec.SchemaOrBool)
	}
	if st.schema.AdditionalProperties.Schema == nil {
		st.schema.AdditionalProperties.Schema = new(spec.Schema)
	}

	st.schema.Typed("object", "")
	return schemaTypable{st.schema.AdditionalProperties.Schema, st.level + 1}
}

func (st schemaTypable) Level() int { return st.level }

func (st schemaTypable) AddExtension(key string, value interface{}) {
	addExtension(&st.schema.VendorExtensible, key, value)
}

func (st schemaTypable) WithEnum(values ...interface{}) {
	st.schema.WithEnum(values...)
}

func (st schemaTypable) WithEnumDescription(desc string) {
	if desc == "" {
		return
	}
	st.AddExtension(extEnumDesc, desc)
}

type schemaValidations struct {
	current *spec.Schema
}

func (sv schemaValidations) SetMaximum(val float64, exclusive bool) {
	sv.current.Maximum = &val
	sv.current.ExclusiveMaximum = exclusive
}
func (sv schemaValidations) SetMinimum(val float64, exclusive bool) {
	sv.current.Minimum = &val
	sv.current.ExclusiveMinimum = exclusive
}
func (sv schemaValidations) SetMultipleOf(val float64)  { sv.current.MultipleOf = &val }
func (sv schemaValidations) SetMinItems(val int64)      { sv.current.MinItems = &val }
func (sv schemaValidations) SetMaxItems(val int64)      { sv.current.MaxItems = &val }
func (sv schemaValidations) SetMinLength(val int64)     { sv.current.MinLength = &val }
func (sv schemaValidations) SetMaxLength(val int64)     { sv.current.MaxLength = &val }
func (sv schemaValidations) SetPattern(val string)      { sv.current.Pattern = val }
func (sv schemaValidations) SetUnique(val bool)         { sv.current.UniqueItems = val }
func (sv schemaValidations) SetDefault(val interface{}) { sv.current.Default = val }
func (sv schemaValidations) SetExample(val interface{}) { sv.current.Example = val }
func (sv schemaValidations) SetEnum(val string) {
	sv.current.Enum = parseEnum(val, &spec.SimpleSchema{Format: sv.current.Format, Type: sv.current.Type[0]})
}

type schemaBuilder struct {
	ctx        *scanCtx
	decl       *entityDecl
	GoName     string
	Name       string
	annotated  bool
	discovered []*entityDecl
	postDecls  []*entityDecl
}

func (s *schemaBuilder) inferNames() (goName string, name string) {
	if s.GoName != "" {
		goName, name = s.GoName, s.Name
		return
	}

	goName = s.decl.Ident.Name
	name = goName
	defer func() {
		s.GoName = goName
		s.Name = name
	}()
	if s.decl.Comments == nil {
		return
	}

DECLS:
	for _, cmt := range s.decl.Comments.List {
		for _, ln := range strings.Split(cmt.Text, "\n") {
			matches := rxModelOverride.FindStringSubmatch(ln)
			if len(matches) > 0 {
				s.annotated = true
			}
			if len(matches) > 1 && len(matches[1]) > 0 {
				name = matches[1]
				break DECLS
			}
		}
	}
	return
}

func (s *schemaBuilder) Build(definitions map[string]spec.Schema) error {
	s.inferNames()

	schema := definitions[s.Name]
	err := s.buildFromDecl(s.decl, &schema)
	if err != nil {
		return err
	}
	definitions[s.Name] = schema
	return nil
}

func (s *schemaBuilder) buildFromDecl(_ *entityDecl, schema *spec.Schema) error {
	// analyze doc comment for the model
	sp := new(sectionedParser)
	sp.setTitle = func(lines []string) { schema.Title = joinDropLast(lines) }
	sp.setDescription = func(lines []string) {
		schema.Description = joinDropLast(lines)
		enumDesc := getEnumDesc(schema.VendorExtensible.Extensions)
		if enumDesc != "" {
			schema.Description += "\n" + enumDesc
		}
	}
	if err := sp.Parse(s.decl.Comments); err != nil {
		return err
	}

	// if the type is marked to ignore, just return
	if sp.ignored {
		return nil
	}

	switch tpe := s.decl.Type.Obj().Type().(type) {
	case *types.Basic:
		debugLog("basic: %v", tpe.Name())
	case *types.Struct:
		if err := s.buildFromStruct(s.decl, tpe, schema, make(map[string]string)); err != nil {
			return err
		}
	case *types.Interface:
		if err := s.buildFromInterface(s.decl, tpe, schema, make(map[string]string)); err != nil {
			return err
		}
	case *types.Array:
		debugLog("array: %v -> %v", s.decl.Ident.Name, tpe.Elem().String())
	case *types.Slice:
		debugLog("slice: %v -> %v", s.decl.Ident.Name, tpe.Elem().String())
	case *types.Map:
		debugLog("map: %v -> [%v]%v", s.decl.Ident.Name, tpe.Key().String(), tpe.Elem().String())
	case *types.Named:
		o := tpe.Obj()
		if o != nil {
			debugLog("got the named type object: %s.%s | isAlias: %t | exported: %t", o.Pkg().Path(), o.Name(), o.IsAlias(), o.Exported())
			if o.Pkg().Name() == "time" && o.Name() == "Time" {
				schema.Typed("string", "date-time")
				return nil

    
func (s *schemaBuilder) createParser(nm string, schema, ps *spec.Schema, fld *ast.Field) *sectionedParser {
	sp := new(sectionedParser)

	schemeType, err := ps.Type.MarshalJSON()
	if err != nil {
		return nil
	}

	if ps.Ref.String() == "" {
		sp.setDescription = func(lines []string) {
			ps.Description = joinDropLast(lines)
			enumDesc := getEnumDesc(ps.VendorExtensible.Extensions)
			if enumDesc != "" {
				ps.Description += "\n" + enumDesc
			}
		}
		sp.taggers = []tagParser{
			newSingleLineTagParser("maximum", &setMaximum{schemaValidations{ps}, rxf(rxMaximumFmt, "")}),
			newSingleLineTagParser("minimum", &setMinimum{schemaValidations{ps}, rxf(rxMinimumFmt, "")}),
			newSingleLineTagParser("multipleOf", &setMultipleOf{schemaValidations{ps}, rxf(rxMultipleOfFmt, "")}),
			newSingleLineTagParser("minLength", &setMinLength{schemaValidations{ps}, rxf(rxMinLengthFmt, "")}),
			newSingleLineTagParser("maxLength", &setMaxLength{schemaValidations{ps}, rxf(rxMaxLengthFmt, "")}),
			newSingleLineTagParser("pattern", &setPattern{schemaValidations{ps}, rxf(rxPatternFmt, "")}),
			newSingleLineTagParser("minItems", &setMinItems{schemaValidations{ps}, rxf(rxMinItemsFmt, "")}),
			newSingleLineTagParser("maxItems", &setMaxItems{schemaValidations{ps}, rxf(rxMaxItemsFmt, "")}),
			newSingleLineTagParser("unique", &setUnique{schemaValidations{ps}, rxf(rxUniqueFmt, "")}),
			newSingleLineTagParser("enum", &setEnum{schemaValidations{ps}, rxf(rxEnumFmt, "")}),
			newSingleLineTagParser("default", &setDefault{&spec.SimpleSchema{Type: string(schemeType)}, schemaValidations{ps}, rxf(rxDefaultFmt, "")}),
			newSingleLineTagParser("type", &setDefault{&spec.SimpleSchema{Type: string(schemeType)}, schemaValidations{ps}, rxf(rxDefaultFmt, "")}),
			newSingleLineTagParser("example", &setExample{&spec.SimpleSchema{Type: string(schemeType)}, schemaValidations{ps}, rxf(rxExampleFmt, "")}),
			newSingleLineTagParser("required", &setRequiredSchema{schema, nm}),
			newSingleLineTagParser("readOnly", &setReadOnlySchema{ps}),
			newSingleLineTagParser("discriminator", &setDiscriminator{schema, nm}),
			newMultiLineTagParser("YAMLExtensionsBlock", newYamlParser(rxExtensions, schemaVendorExtensibleSetter(ps)), true),
		}

		itemsTaggers := func(items *spec.Schema, level int) []tagParser {
			schemeType, err := items.Type.MarshalJSON()
			if err != nil {
				return nil
			}
			// the expression is 1-index based not 0-index
			itemsPrefix := fmt.Sprintf(rxItemsPrefixFmt, level+1)
			return []tagParser{
				newSingleLineTagParser(fmt.Sprintf("items%dMaximum", level), &setMaximum{schemaValidations{items}, rxf(rxMaximumFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMinimum", level), &setMinimum{schemaValidations{items}, rxf(rxMinimumFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMultipleOf", level), &setMultipleOf{schemaValidations{items}, rxf(rxMultipleOfFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMinLength", level), &setMinLength{schemaValidations{items}, rxf(rxMinLengthFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMaxLength", level), &setMaxLength{schemaValidations{items}, rxf(rxMaxLengthFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dPattern", level), &setPattern{schemaValidations{items}, rxf(rxPatternFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMinItems", level), &setMinItems{schemaValidations{items}, rxf(rxMinItemsFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dMaxItems", level), &setMaxItems{schemaValidations{items}, rxf(rxMaxItemsFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dUnique", level), &setUnique{schemaValidations{items}, rxf(rxUniqueFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dEnum", level), &setEnum{schemaValidations{items}, rxf(rxEnumFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dDefault", level), &setDefault{&spec.SimpleSchema{Type: string(schemeType)}, schemaValidations{items}, rxf(rxDefaultFmt, itemsPrefix)}),
				newSingleLineTagParser(fmt.Sprintf("items%dExample", level), &setExample{&spec.SimpleSchema{Type: string(schemeType)}, schemaValidations{items}, rxf(rxExampleFmt, itemsPrefix)}),
			}
		}

		var parseArrayTypes func(expr ast.Expr, items *spec.SchemaOrArray, level int) ([]tagParser, error)
		parseArrayTypes = func(expr ast.Expr, items *spec.SchemaOrArray, level int) ([]tagParser, error) {
			if items == nil || items.Schema == nil {
				return []tagParser{}, nil
			}
			switch iftpe := expr.(type) {
			case *ast.ArrayType:
				eleTaggers := itemsTaggers(items.Schema, level)
				sp.taggers = append(eleTaggers, sp.taggers...)
				otherTaggers, err := parseArrayTypes(iftpe.Elt, items.Schema.Items, level+1)
				if err != nil {
					return nil, err
				}
				return otherTaggers, nil
			case *ast.Ident:
				taggers := []tagParser{}
				if iftpe.Obj == nil {
					taggers = itemsTaggers(items.Schema, level)
				}
				otherTaggers, err := parseArrayTypes(expr, items.Schema.Items, level+1)
				if err != nil {
					return nil, err
				}
				return append(taggers, otherTaggers...), nil
			case *ast.StarExpr:
				otherTaggers, err := parseArrayTypes(iftpe.X, items, level)
				if err != nil {
					return nil, err
				}
				return otherTaggers, nil
			default:
				return nil, fmt.Errorf("unknown field type ele for %q", nm)
			}
		}
		// check if this is a primitive, if so parse the validations from the
		// doc comments of the slice declaration.
		if ftped, ok := fld.Type.(*ast.ArrayType); ok {
			taggers, err := parseArrayTypes(ftped.Elt, ps.Items, 0)
			if err != nil {
				return sp
			}
			sp.taggers = append(taggers, sp.taggers...)
		}

	} else {
		sp.taggers = []tagParser{
			newSingleLineTagParser("required", &setRequiredSchema{schema, nm}),
		}
	}
	return sp
}