Class: RubyLsp::GlobalState

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_lsp/global_state.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGlobalState

: -> void



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ruby_lsp/global_state.rb', line 37

def initialize
  @workspace_uri = URI::Generic.from_path(path: Dir.pwd) #: URI::Generic
  @encoding = Encoding::UTF_8 #: Encoding

  @formatter = "auto" #: String
  @linters = [] #: Array[String]
  @test_library = "minitest" #: String
  @has_type_checker = true #: bool
  @index = RubyIndexer::Index.new #: RubyIndexer::Index
  @supported_formatters = {} #: Hash[String, Requests::Support::Formatter]
  @type_inferrer = TypeInferrer.new(@index) #: TypeInferrer
  @addon_settings = {} #: Hash[String, untyped]
  @top_level_bundle = begin
    Bundler.with_original_env { Bundler.default_gemfile }
    true
  rescue Bundler::GemfileNotFound, Bundler::GitError
    false
  end #: bool
  @client_capabilities = ClientCapabilities.new #: ClientCapabilities
  @enabled_feature_flags = {} #: Hash[Symbol, bool]
  @mutex = Mutex.new #: Mutex
  @telemetry_machine_id = nil #: String?
  @feature_configuration = {
    inlayHint: RequestConfig.new({
      enableAll: false,
      implicitRescue: false,
      implicitHashValue: false,
    }),
    codeLens: RequestConfig.new({
      enableAll: false,
      enableTestCodeLens: true,
    }),
  } #: Hash[Symbol, RequestConfig]
end

Instance Attribute Details

#client_capabilitiesObject (readonly)

: ClientCapabilities



28
29
30
# File 'lib/ruby_lsp/global_state.rb', line 28

def client_capabilities
  @client_capabilities
end

#encodingObject (readonly)

: Encoding



19
20
21
# File 'lib/ruby_lsp/global_state.rb', line 19

def encoding
  @encoding
end

#formatterObject

: String



10
11
12
# File 'lib/ruby_lsp/global_state.rb', line 10

def formatter
  @formatter
end

#has_type_checkerObject (readonly)

: bool



13
14
15
# File 'lib/ruby_lsp/global_state.rb', line 13

def has_type_checker
  @has_type_checker
end

#indexObject (readonly)

: RubyIndexer::Index



16
17
18
# File 'lib/ruby_lsp/global_state.rb', line 16

def index
  @index
end

#telemetry_machine_idObject (readonly)

: String?



34
35
36
# File 'lib/ruby_lsp/global_state.rb', line 34

def telemetry_machine_id
  @telemetry_machine_id
end

#test_libraryObject (readonly)

: String



7
8
9
# File 'lib/ruby_lsp/global_state.rb', line 7

def test_library
  @test_library
end

#top_level_bundleObject (readonly)

: bool



22
23
24
# File 'lib/ruby_lsp/global_state.rb', line 22

def top_level_bundle
  @top_level_bundle
end

#type_inferrerObject (readonly)

: TypeInferrer



25
26
27
# File 'lib/ruby_lsp/global_state.rb', line 25

def type_inferrer
  @type_inferrer
end

#workspace_uriObject (readonly)

: URI::Generic



31
32
33
# File 'lib/ruby_lsp/global_state.rb', line 31

def workspace_uri
  @workspace_uri
end

Instance Method Details

#active_formatterObject

: -> Requests::Support::Formatter?



88
89
90
# File 'lib/ruby_lsp/global_state.rb', line 88

def active_formatter
  @supported_formatters[@formatter]
end

#active_lintersObject

: -> Array



93
94
95
# File 'lib/ruby_lsp/global_state.rb', line 93

def active_linters
  @linters.filter_map { |name| @supported_formatters[name] }
end

#apply_options(options) ⇒ Object

Applies the options provided by the editor and returns an array of notifications to send back to the client : (Hash[Symbol, untyped] options) -> Array



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/ruby_lsp/global_state.rb', line 99

def apply_options(options)
  notifications = []
  direct_dependencies = gather_direct_dependencies
  all_dependencies = gather_direct_and_indirect_dependencies
  workspace_uri = options.dig(:workspaceFolders, 0, :uri)
  @workspace_uri = URI(workspace_uri) if workspace_uri

  specified_formatter = options.dig(:initializationOptions, :formatter)
  rubocop_has_addon = defined?(::RuboCop::Version::STRING) &&
    Gem::Requirement.new(">= 1.70.0").satisfied_by?(Gem::Version.new(::RuboCop::Version::STRING))

  if specified_formatter
    @formatter = specified_formatter

    if specified_formatter != "auto"
      notifications << Notification.window_log_message("Using formatter specified by user: #{@formatter}")
    end

    # If the user had originally configured to use `rubocop`, but their version doesn't provide the add-on yet,
    # fallback to the internal integration
    if specified_formatter == "rubocop" && !rubocop_has_addon
      @formatter = "rubocop_internal"
    end
  end

  if @formatter == "auto"
    @formatter = detect_formatter(direct_dependencies, all_dependencies)
    notifications << Notification.window_log_message("Auto detected formatter: #{@formatter}")
  end

  specified_linters = options.dig(:initializationOptions, :linters)

  if specified_formatter == "rubocop" || specified_linters&.include?("rubocop")
    notifications << Notification.window_log_message("      Formatter is configured to be `rubocop`. As of RuboCop v1.70.0, this identifier activates the add-on\n      implemented in the rubocop gem itself instead of the internal integration provided by the Ruby LSP.\n\n      If you wish to use the internal integration, please configure the formatter as `rubocop_internal`.\n    MESSAGE\n  end\n\n  # If the user had originally configured to use `rubocop`, but their version doesn't provide the add-on yet,\n  # fall back to the internal integration\n  if specified_linters&.include?(\"rubocop\") && !rubocop_has_addon\n    specified_linters.delete(\"rubocop\")\n    specified_linters << \"rubocop_internal\"\n  end\n\n  @linters = specified_linters || detect_linters(direct_dependencies, all_dependencies)\n\n  notifications << if specified_linters\n    Notification.window_log_message(\"Using linters specified by user: \#{@linters.join(\", \")}\")\n  else\n    Notification.window_log_message(\"Auto detected linters: \#{@linters.join(\", \")}\")\n  end\n\n  @test_library = detect_test_library(direct_dependencies)\n  notifications << Notification.window_log_message(\"Detected test library: \#{@test_library}\")\n\n  @has_type_checker = detect_typechecker(all_dependencies)\n  if @has_type_checker\n    notifications << Notification.window_log_message(\n      \"Ruby LSP detected this is a Sorbet project and will defer to the Sorbet LSP for some functionality\",\n    )\n  end\n\n  encodings = options.dig(:capabilities, :general, :positionEncodings)\n  @encoding = if !encodings || encodings.empty?\n    Encoding::UTF_16LE\n  elsif encodings.include?(Constant::PositionEncodingKind::UTF8)\n    Encoding::UTF_8\n  elsif encodings.include?(Constant::PositionEncodingKind::UTF16)\n    Encoding::UTF_16LE\n  else\n    Encoding::UTF_32\n  end\n  @index.configuration.encoding = @encoding\n\n  @client_capabilities.apply_client_capabilities(options[:capabilities]) if options[:capabilities]\n\n  addon_settings = options.dig(:initializationOptions, :addonSettings)\n  if addon_settings\n    addon_settings.transform_keys!(&:to_s)\n    @addon_settings.merge!(addon_settings)\n  end\n\n  enabled_flags = options.dig(:initializationOptions, :enabledFeatureFlags)\n  @enabled_feature_flags = enabled_flags if enabled_flags\n\n  @telemetry_machine_id = options.dig(:initializationOptions, :telemetryMachineId)\n\n  options.dig(:initializationOptions, :featuresConfiguration)&.each do |feature_name, config|\n    @feature_configuration[feature_name]&.merge!(config)\n  end\n\n  notifications\nend\n", type: Constant::MessageType::WARNING)

#enabled_feature?(flag) ⇒ Boolean

: (Symbol flag) -> bool?



203
204
205
# File 'lib/ruby_lsp/global_state.rb', line 203

def enabled_feature?(flag)
  @enabled_feature_flags[:all] || @enabled_feature_flags[flag]
end

#encoding_nameObject

: -> String



213
214
215
216
217
218
219
220
221
222
# File 'lib/ruby_lsp/global_state.rb', line 213

def encoding_name
  case @encoding
  when Encoding::UTF_8
    Constant::PositionEncodingKind::UTF8
  when Encoding::UTF_16LE
    Constant::PositionEncodingKind::UTF16
  else
    Constant::PositionEncodingKind::UTF32
  end
end

#feature_configuration(feature_name) ⇒ Object

: (Symbol) -> RequestConfig?



198
199
200
# File 'lib/ruby_lsp/global_state.rb', line 198

def feature_configuration(feature_name)
  @feature_configuration[feature_name]
end

#register_formatter(identifier, instance) ⇒ Object

: (String identifier, Requests::Support::Formatter instance) -> void



83
84
85
# File 'lib/ruby_lsp/global_state.rb', line 83

def register_formatter(identifier, instance)
  @supported_formatters[identifier] = instance
end

#settings_for_addon(addon_name) ⇒ Object

: (String addon_name) -> Hash[Symbol, untyped]?



78
79
80
# File 'lib/ruby_lsp/global_state.rb', line 78

def settings_for_addon(addon_name)
  @addon_settings[addon_name]
end

#supports_watching_filesObject

: -> bool



225
226
227
# File 'lib/ruby_lsp/global_state.rb', line 225

def supports_watching_files
  @client_capabilities.supports_watching_files
end

#synchronize(&block) ⇒ Object

: [T] { -> T } -> T



73
74
75
# File 'lib/ruby_lsp/global_state.rb', line 73

def synchronize(&block)
  @mutex.synchronize(&block)
end

#workspace_pathObject

: -> String



208
209
210
# File 'lib/ruby_lsp/global_state.rb', line 208

def workspace_path
  @workspace_uri.to_standardized_path #: as !nil
end