Class: Graphlyte::Editors::AnnotateTypes

Inherits:
Object
  • Object
show all
Defined in:
lib/graphlyte/editors/annotate_types.rb

Overview

Use a schema definition to annotate the type of each field and variable reference.

Constant Summary collapse

TypeCheckError =
Class.new(StandardError)
TypeNotFound =
Class.new(TypeCheckError)
FieldNotFound =
Class.new(TypeCheckError)
CannotDetermineTypeName =
Class.new(TypeCheckError)

Instance Method Summary collapse

Constructor Details

#initialize(schema, recheck: false) ⇒ AnnotateTypes

Returns a new instance of AnnotateTypes.



12
13
14
15
# File 'lib/graphlyte/editors/annotate_types.rb', line 12

def initialize(schema, recheck: false)
  @schema = schema
  @recheck = recheck
end

Instance Method Details

#edit(doc) ⇒ Object



17
18
19
20
21
22
# File 'lib/graphlyte/editors/annotate_types.rb', line 17

def edit(doc)
  return if !recheck && doc.schema # Previously annotated

  doc.schema = @schema
  editor.edit(doc)
end

#editorObject



24
25
26
27
28
29
30
31
32
# File 'lib/graphlyte/editors/annotate_types.rb', line 24

def editor
  @editor ||=
    Editor
    .top_down
    .on_field { |field, action| infer_field(field, action.parent, action.document) }
    .on_variable_reference do |ref, action|
      infer_ref(ref, action.closest(Syntax::Argument), action.closest(Syntax::Field))
    end
end

#infer_field(field, parent, document) ⇒ Object

Raises:



44
45
46
47
48
49
50
51
# File 'lib/graphlyte/editors/annotate_types.rb', line 44

def infer_field(field, parent, document)
  name = object_name(parent, document)
  object_type = type(name)

  raise FieldNotFound, "#{object_name}.#{field.name}" unless object_type.fields.key?(field.name)

  field.type = Syntax::Type.from_type_ref(object_type.fields[field.name].type)
end

#infer_ref(ref, argument, field) ⇒ Object

For now we are ignoring variables nested in input objects. TODO: encode input objects differently?

Raises:

  • (ArgumentNotFound)


36
37
38
39
40
41
42
# File 'lib/graphlyte/editors/annotate_types.rb', line 36

def infer_ref(ref, argument, field)
  type = @schema.types[field.type.unpack]
  arg = type.arguments[argument.name]
  raise ArgumentNotFound, "#{type.name}.#{field.name}(#{argument.name})" unless arg

  ref.inferred_type = Syntax::Type.from_type_ref(arg.type)
end

#object_name(parent, document) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/graphlyte/editors/annotate_types.rb', line 60

def object_name(parent, document)
  case parent
  when Syntax::FragmentSpread
    fragment = document.fragments[parent.name]
    raise CannotDetermineTypeName, parent unless fragment

    fragment.type_name
  when Syntax::InlineFragment, Syntax::Fragment
    parent.type_name
  when Syntax::Field
    parent.type.unpack
  end
end

#type(name) ⇒ Object

Raises:



53
54
55
56
57
58
# File 'lib/graphlyte/editors/annotate_types.rb', line 53

def type(name)
  object_type = @schema.types[name]
  raise TypeNotFound, object_name unless object_type

  object_type
end