def content_for(target:, path:, line:, column:)
def content_for(target:, path:, line:, column:)
file = service.source_files[path] or return
typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
node, *parents = typing.source.find_nodes(line: line, column: column)
if node && parents
case node.type
when :lvar
var_name = node.children[0]
context = typing.context_at(line: line, column: column)
var_type = context.type_env[var_name] || AST::Types::Any.new(location: nil)
return VariableContent.new(node: node, name: var_name, type: var_type, location: node.location.name)
when :lvasgn
var_name, rhs = node.children
context = typing.context_at(line: line, column: column)
type = context.type_env[var_name] || typing.type_of(node: node)
return VariableContent.new(node: node, name: var_name, type: type, location: node.location.name)
when :send, :csend
result_node =
case parents[0]&.type
when :block, :numblock
if node == parents[0].children[0]
parents[0]
else
node
end
else
node
end
case call = typing.call_of(node: result_node)
when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
unless call.method_decls.empty?
return MethodCallContent.new(
node: result_node,
method_call: call,
location: node.location.selector
)
end
end
when :def, :defs
context = typing.context_at(line: line, column: column)
method_context = context.method_context
if method_context && method_context.method
return DefinitionContent.new(
node: node,
method_name: method_name_from_method(method_context, builder: context.factory.definition_builder),
method_type: method_context.method_type,
definition: method_context.method,
location: node.loc.name
)
end
when :const, :casgn
context = typing.context_at(line: line, column: column)
type = typing.type_of(node: node)
const_name = typing.source_index.reference(constant_node: node)
if const_name
entry = context.env.constant_entry(const_name) or return
return ConstantContent.new(
location: node.location.name,
full_name: const_name,
type: type,
decl: entry
)
end
when :assertion
original_node, _ = node.children
original_type = typing.type_of(node: original_node)
asserted_type = typing.type_of(node: node)
if original_type != asserted_type
return TypeAssertionContent.new(node: node, original_type: original_type, asserted_type: asserted_type, location: node.location.expression)
end
end
TypeContent.new(
node: node,
type: typing.type_of(node: node),
location: node.location.expression
)
end
end