Class: GraphQL::Modernize::ContextBuilder
- Inherits:
-
Object
- Object
- GraphQL::Modernize::ContextBuilder
- Defined in:
- lib/graphql/modernize/context_builder.rb
Instance Method Summary collapse
- #argument_call(node) ⇒ Object
- #call_receiver?(node) ⇒ Boolean
- #context_at(byte_offset) ⇒ Object
- #executable_scope_at?(byte_offset) ⇒ Boolean
-
#initialize(source_file, hierarchy) ⇒ ContextBuilder
constructor
A new instance of ContextBuilder.
- #top_level_statement?(node) ⇒ Boolean
Constructor Details
#initialize(source_file, hierarchy) ⇒ ContextBuilder
Returns a new instance of ContextBuilder.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/graphql/modernize/context_builder.rb', line 8 def initialize(source_file, hierarchy) nodes = {} scopes = [] @call_receivers = {}.compare_by_identity @argument_calls = {}.compare_by_identity @top_level_statements = {}.compare_by_identity source_file.ast.statements.body.each { |node| @top_level_statements[node] = true } # ponytail: nested calls rescan descendants; add a parent index only if deep DSLs become a bottleneck. record_arguments = lambda do |call| stack = call.arguments&.arguments&.dup || [] until stack.empty? argument = stack.pop @argument_calls[argument] = call stack.concat(argument.compact_child_nodes) end end dispatcher = Astel::Dispatcher.new callback = ->(node) { nodes[node.location.start_offset] = node } dispatcher.on(:class_node, callback) dispatcher.on(:module_node, callback) dispatcher.on(:def_node) { |node| scopes << node } dispatcher.on(:lambda_node) { |node| scopes << node } dispatcher.on(:call_node) do |node| @call_receivers[node.receiver] = true if node.receiver record_arguments.call(node) scopes << node.block if node.block && (node.receiver || node.name != :field) end dispatcher.run(source_file.ast) @executable_scopes = scopes.map do |scope| [scope.location.start_offset, scope.location.end_offset] end.sort_by(&:first) @ranges = hierarchy.declarations.fetch(source_file.path, {}).values.map do |declaration| context = Context.new( class_stack: declaration.name.split("::"), superclass: declaration.superclass, graphql_kind: hierarchy.resolve_kind(declaration.name), class_name: declaration.name, class_node: nodes[declaration.start_offset] ) [declaration.start_offset, declaration.end_offset, context] end.sort_by(&:first) end |
Instance Method Details
#argument_call(node) ⇒ Object
73 |
# File 'lib/graphql/modernize/context_builder.rb', line 73 def argument_call(node) = @argument_calls[node] |
#call_receiver?(node) ⇒ Boolean
71 |
# File 'lib/graphql/modernize/context_builder.rb', line 71 def call_receiver?(node) = @call_receivers.key?(node) |
#context_at(byte_offset) ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'lib/graphql/modernize/context_builder.rb', line 52 def context_at(byte_offset) index = @ranges.bsearch_index { |start_offset, _end_offset, _context| start_offset > byte_offset } index = index ? index - 1 : @ranges.length - 1 index.downto(0) do |candidate| start_offset, end_offset, context = @ranges[candidate] return context if byte_offset >= start_offset && byte_offset < end_offset end nil end |
#executable_scope_at?(byte_offset) ⇒ Boolean
62 63 64 65 66 67 68 69 |
# File 'lib/graphql/modernize/context_builder.rb', line 62 def executable_scope_at?(byte_offset) index = @executable_scopes.bsearch_index { |start_offset, _end_offset| start_offset >= byte_offset } index = index ? index - 1 : @executable_scopes.length - 1 index.downto(0).any? do |candidate| start_offset, end_offset = @executable_scopes[candidate] byte_offset > start_offset && byte_offset < end_offset end end |
#top_level_statement?(node) ⇒ Boolean
75 |
# File 'lib/graphql/modernize/context_builder.rb', line 75 def top_level_statement?(node) = @top_level_statements.key?(node) |