Module: RubyLsp::Requests::Support::Common

Overview

@requires_ancestor: Kernel

Instance Method Summary collapse

Instance Method Details

#categorized_markdown_from_index_entries(title, entries, max_entries = nil) ⇒ Object

: (String title, (Array | RubyIndexer::Entry) entries, ?Integer? max_entries) -> Hash[Symbol, String]



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/ruby_lsp/requests/support/common.rb', line 68

def categorized_markdown_from_index_entries(title, entries, max_entries = nil)
  markdown_title = "```ruby\n#{title}\n```"
  definitions = []
  content = +""
  entries = Array(entries)
  entries_to_format = max_entries ? entries.take(max_entries) : entries
  entries_to_format.each do |entry|
    loc = entry.location

    # We always handle locations as zero based. However, for file links in Markdown we need them to be one
    # based, which is why instead of the usual subtraction of 1 to line numbers, we are actually adding 1 to
    # columns. The format for VS Code file URIs is
    # `file:///path/to/file.rb#Lstart_line,start_column-end_line,end_column`
    uri = "#{entry.uri}#L#{loc.start_line},#{loc.start_column + 1}-#{loc.end_line},#{loc.end_column + 1}"
    definitions << "[#{entry.file_name}](#{uri})"
    content << "\n\n#{entry.comments}" unless entry.comments.empty?
  end

  additional_entries_text = if max_entries && entries.length > max_entries
    additional = entries.length - max_entries
    " | #{additional} other#{additional > 1 ? "s" : ""}"
  else
    ""
  end

  {
    title: markdown_title,
    links: "**Definitions**: #{definitions.join(" | ")}#{additional_entries_text}",
    documentation: content,
  }
end

#constant_name(node) ⇒ Object

: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String?



117
118
119
# File 'lib/ruby_lsp/requests/support/common.rb', line 117

def constant_name(node)
  RubyIndexer::Index.constant_name(node)
end

#create_code_lens(node, title:, command_name:, arguments:, data:) ⇒ Object

: (Prism::Node node, title: String, command_name: String, arguments: Array?, data: Hash[untyped, untyped]?) -> Interface::CodeLens



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ruby_lsp/requests/support/common.rb', line 38

def create_code_lens(node, title:, command_name:, arguments:, data:)
  range = range_from_node(node)

  Interface::CodeLens.new(
    range: range,
    command: Interface::Command.new(
      title: title,
      command: command_name,
      arguments: arguments,
    ),
    data: data,
  )
end

#each_constant_path_part(node, &block) ⇒ Object

Iterates over each part of a constant path, so that we can easily push response items for each section of the name. For example, for ‘Foo::Bar::Baz`, this method will invoke the block with `Foo`, then `Bar` and finally `Baz`. : (Prism::Node node) { (Prism::Node part) -> void } -> void



134
135
136
137
138
139
140
141
# File 'lib/ruby_lsp/requests/support/common.rb', line 134

def each_constant_path_part(node, &block)
  current = node #: Prism::Node?

  while current.is_a?(Prism::ConstantPathNode)
    block.call(current)
    current = current.parent
  end
end

#kind_for_entry(entry) ⇒ Object

: (RubyIndexer::Entry entry) -> Integer



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/ruby_lsp/requests/support/common.rb', line 144

def kind_for_entry(entry)
  case entry
  when RubyIndexer::Entry::Class
    Constant::SymbolKind::CLASS
  when RubyIndexer::Entry::Module
    Constant::SymbolKind::NAMESPACE
  when RubyIndexer::Entry::Constant, RubyIndexer::Entry::UnresolvedConstantAlias, RubyIndexer::Entry::ConstantAlias
    Constant::SymbolKind::CONSTANT
  when RubyIndexer::Entry::Method, RubyIndexer::Entry::UnresolvedMethodAlias, RubyIndexer::Entry::MethodAlias
    entry.name == "initialize" ? Constant::SymbolKind::CONSTRUCTOR : Constant::SymbolKind::METHOD
  when RubyIndexer::Entry::Accessor
    Constant::SymbolKind::PROPERTY
  when RubyIndexer::Entry::InstanceVariable, RubyIndexer::Entry::ClassVariable
    Constant::SymbolKind::FIELD
  when RubyIndexer::Entry::GlobalVariable
    Constant::SymbolKind::VARIABLE
  else
    Constant::SymbolKind::NULL
  end
end

#markdown_from_index_entries(title, entries, max_entries = nil, extra_links: nil) ⇒ Object

: (String title, (Array | RubyIndexer::Entry) entries, ?Integer? max_entries, ?extra_links: String?) -> String



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ruby_lsp/requests/support/common.rb', line 101

def markdown_from_index_entries(title, entries, max_entries = nil, extra_links: nil)
  categorized_markdown = categorized_markdown_from_index_entries(title, entries, max_entries)

  markdown = +(categorized_markdown[:title] || "")
  markdown << "\n\n#{extra_links}" if extra_links

  <<~MARKDOWN.chomp
    #{markdown}

    #{categorized_markdown[:links]}

    #{categorized_markdown[:documentation]}
  MARKDOWN
end

#namespace_constant_name(node) ⇒ Object

: ((Prism::ModuleNode | Prism::ClassNode) node) -> String?



122
123
124
125
126
127
128
# File 'lib/ruby_lsp/requests/support/common.rb', line 122

def namespace_constant_name(node)
  path = node.constant_path
  case path
  when Prism::ConstantPathNode, Prism::ConstantReadNode
    constant_name(path)
  end
end

#not_in_dependencies?(file_path) ⇒ Boolean

: (String file_path) -> bool?

Returns:

  • (Boolean)


53
54
55
56
57
58
59
# File 'lib/ruby_lsp/requests/support/common.rb', line 53

def not_in_dependencies?(file_path)
  BUNDLE_PATH &&
    !file_path.start_with?(
      BUNDLE_PATH, #: as !nil
    ) &&
    !file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
end

#range_from_location(location) ⇒ Object

: ((Prism::Location | RubyIndexer::Location) location) -> Interface::Range



27
28
29
30
31
32
33
34
35
# File 'lib/ruby_lsp/requests/support/common.rb', line 27

def range_from_location(location)
  Interface::Range.new(
    start: Interface::Position.new(
      line: location.start_line - 1,
      character: location.start_column,
    ),
    end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
  )
end

#range_from_node(node) ⇒ Object

: (Prism::Node node) -> Interface::Range



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ruby_lsp/requests/support/common.rb', line 14

def range_from_node(node)
  loc = node.location

  Interface::Range.new(
    start: Interface::Position.new(
      line: loc.start_line - 1,
      character: loc.start_column,
    ),
    end: Interface::Position.new(line: loc.end_line - 1, character: loc.end_column),
  )
end

#self_receiver?(node) ⇒ Boolean

: (Prism::CallNode node) -> bool

Returns:

  • (Boolean)


62
63
64
65
# File 'lib/ruby_lsp/requests/support/common.rb', line 62

def self_receiver?(node)
  receiver = node.receiver
  receiver.nil? || receiver.is_a?(Prism::SelfNode)
end