Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate indexing configuration to editor settings #2300

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .index.yml

This file was deleted.

73 changes: 46 additions & 27 deletions lib/ruby_lsp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ def run_initialize(message)
)
end

process_indexing_configuration(options.dig(:initializationOptions, :indexing))

begin_progress("indexing-progress", "Ruby LSP: indexing files")
end

Expand All @@ -251,36 +253,14 @@ def run_initialized
load_addons
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)

indexing_config = {}

# Need to use the workspace URI, otherwise, this will fail for people working on a project that is a symlink.
index_path = File.join(@global_state.workspace_path, ".index.yml")

if File.exist?(index_path)
begin
indexing_config = YAML.parse_file(index_path).to_ruby
rescue Psych::SyntaxError => e
message = "Syntax error while loading configuration: #{e.message}"
send_message(
Notification.new(
method: "window/showMessage",
params: Interface::ShowMessageParams.new(
type: Constant::MessageType::WARNING,
message: message,
),
),
)
end
end

if defined?(Requests::Support::RuboCopFormatter)
@global_state.register_formatter("rubocop", Requests::Support::RuboCopFormatter.new)
end
if defined?(Requests::Support::SyntaxTreeFormatter)
@global_state.register_formatter("syntax_tree", Requests::Support::SyntaxTreeFormatter.new)
end

perform_initial_indexing(indexing_config)
perform_initial_indexing
check_formatter_is_available
end

Expand Down Expand Up @@ -766,12 +746,10 @@ def shutdown
Addon.addons.each(&:deactivate)
end

sig { params(config_hash: T::Hash[String, T.untyped]).void }
def perform_initial_indexing(config_hash)
sig { void }
def perform_initial_indexing
# The begin progress invocation happens during `initialize`, so that the notification is sent before we are
# stuck indexing files
RubyIndexer.configuration.apply_config(config_hash)

Thread.new do
begin
RubyIndexer::RBSIndexer.new(@global_state.index).index_ruby_core
Expand Down Expand Up @@ -872,5 +850,46 @@ def check_formatter_is_available
)
end
end

sig { params(indexing_options: T.nilable(T::Hash[Symbol, T.untyped])).void }
def process_indexing_configuration(indexing_options)
# Need to use the workspace URI, otherwise, this will fail for people working on a project that is a symlink.
index_path = File.join(@global_state.workspace_path, ".index.yml")

if File.exist?(index_path)
begin
RubyIndexer.configuration.apply_config(YAML.parse_file(index_path).to_ruby)
send_message(
Notification.new(
method: "window/showMessage",
params: Interface::ShowMessageParams.new(
type: Constant::MessageType::WARNING,
message: "The .index.yml configuration file is deprecated. " \
"Please use editor settings to configure the index",
),
),
)
rescue Psych::SyntaxError => e
message = "Syntax error while loading configuration: #{e.message}"
send_message(
Notification.new(
method: "window/showMessage",
params: Interface::ShowMessageParams.new(
type: Constant::MessageType::WARNING,
message: message,
),
),
)
end
return
end

return unless indexing_options

# The index expects snake case configurations, but VS Code standardizes on camel case settings
RubyIndexer.configuration.apply_config(
indexing_options.transform_keys { |key| key.to_s.gsub(/([A-Z])/, "_\\1").downcase },
)
end
end
end
3 changes: 3 additions & 0 deletions lsp.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"**/out": true,
},
"rubyLsp.bypassTypechecker": true,
"rubyLsp.excludedPatterns": [
"**/test/fixtures/**/*.rb"
],
"typescript.tsc.autoDetect": "off",
}
}
29 changes: 26 additions & 3 deletions test/server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -325,18 +325,21 @@ def test_initialize_features_with_enable_all_configuration
end

def test_handles_invalid_configuration
FileUtils.mv(".index.yml", ".index.yml.tmp")
File.write(".index.yml", "} invalid yaml")

@server.process_message({ method: "initialized" })
capture_subprocess_io do
@server.process_message(id: 1, method: "initialize", params: {})
end

@server.pop_response
notification = @server.pop_response
assert_equal("window/showMessage", notification.method)
assert_match(
/Syntax error while loading configuration/,
T.cast(notification.params, RubyLsp::Interface::ShowMessageParams).message,
)
ensure
FileUtils.mv(".index.yml.tmp", ".index.yml")
FileUtils.rm(".index.yml")
end

def test_shows_error_if_formatter_set_to_rubocop_but_rubocop_not_available
Expand Down Expand Up @@ -462,6 +465,26 @@ def test_errors_include_telemetry_data
assert_match("mocha/exception_raiser.rb", data[:backtrace])
end

def test_handles_editor_indexing_settings
capture_io do
@server.process_message({
id: 1,
method: "initialize",
params: {
initializationOptions: {
indexing: {
excludedGems: ["foo_gem"],
includedGems: ["bar_gem"],
},
},
},
})
end

assert_includes(RubyIndexer.configuration.instance_variable_get(:@excluded_gems), "foo_gem")
assert_includes(RubyIndexer.configuration.instance_variable_get(:@included_gems), "bar_gem")
end

private

def with_uninstalled_rubocop(&block)
Expand Down
41 changes: 41 additions & 0 deletions vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,47 @@
"rubyLsp.rubyExecutablePath": {
"description": "Path to the Ruby installation. This is used as a fallback if version manager activation fails",
"type": "string"
},
"rubyLsp.indexing": {
"description": "Indexing configurations. Modifying these will impact which declarations are available for definition, completion and other features",
"type": "object",
"properties": {
"excludedPatterns": {
"type": "array",
"description": "List of glob patterns to exclude from indexing. For excluding gems, use excludedGems instead.",
"items": {
"type": "string"
}
},
"includedPatterns": {
"type": "array",
"description": "List of glob patterns to include when indexing. For example, Ruby files that do not have the .rb extension.",
"items": {
"type": "string"
}
},
"includedGems": {
"type": "array",
"description": "List of gems to include when indexing. You should only use this setting to include development gems in indexing (which are auto excluded).",
"items": {
"type": "string"
}
},
"excludedGems": {
"type": "array",
"description": "List of gems to exclude from indexing. For example, gems that are not intended to have their declarations referenced from the application.",
"items": {
"type": "string"
}
},
"excludedMagicComments": {
"type": "array",
"description": "List of magic comments that should not be considered as documentation for declarations.",
"items": {
"type": "string"
}
}
}
}
}
},
Expand Down
1 change: 1 addition & 0 deletions vscode/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ function collectClientOptions(
featuresConfiguration: configuration.get("featuresConfiguration"),
formatter: configuration.get("formatter"),
linters: configuration.get("linters"),
indexing: configuration.get("indexing"),
},
};
}
Expand Down
Loading