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

Move codebase to typed strict #127

Merged
merged 9 commits into from
Jun 9, 2022
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
11 changes: 10 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ Sorbet/FalseSigil:
Sorbet/TrueSigil:
Enabled: true
Include:
- "**/*.rb"
- "test/**/*.rb"
Exclude:
- "**/*.rake"
- "lib/**/*.rb"

Sorbet/StrictSigil:
Enabled: true
Include:
- "lib/**/*.rb"
Exclude:
- "**/*.rake"
- "test/**/*.rb"
2 changes: 1 addition & 1 deletion lib/internal.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"
Expand Down
4 changes: 2 additions & 2 deletions lib/ruby-lsp.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
VERSION = File.read(File.expand_path("../VERSION", __dir__)).strip
VERSION = T.let(File.read(File.expand_path("../VERSION", __dir__)).strip, String)
end
8 changes: 7 additions & 1 deletion lib/ruby_lsp/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ def ==(other)
@source == other.source
end

sig { params(request_name: Symbol, block: T.proc.params(document: Document).returns(T.untyped)).returns(T.untyped) }
sig do
type_parameters(:T)
.params(
request_name: Symbol,
block: T.proc.params(document: Document).returns(T.type_parameter(:T))
).returns(T.type_parameter(:T))
end
def cache_fetch(request_name, &block)
cached = @cache[request_name]
return cached if cached
Expand Down
33 changes: 21 additions & 12 deletions lib/ruby_lsp/handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,26 +114,26 @@ def respond_with_capabilities(enabled_features)
sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol]) }
def respond_with_document_symbol(uri)
store.cache_fetch(uri, :document_symbol) do |document|
RubyLsp::Requests::DocumentSymbol.run(document)
RubyLsp::Requests::DocumentSymbol.new(document).run
end
end

sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::FoldingRange]) }
def respond_with_folding_ranges(uri)
store.cache_fetch(uri, :folding_ranges) do |document|
Requests::FoldingRanges.run(document)
Requests::FoldingRanges.new(document).run
end
end

sig do
params(
uri: String,
positions: T::Array[Document::PositionShape]
).returns(T::Array[RubyLsp::Requests::Support::SelectionRange])
).returns(T::Array[T.nilable(RubyLsp::Requests::Support::SelectionRange)])
end
def respond_with_selection_ranges(uri, positions)
ranges = store.cache_fetch(uri, :selection_ranges) do |document|
Requests::SelectionRanges.run(document)
Requests::SelectionRanges.new(document).run
end

# Per the selection range request spec (https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange),
Expand All @@ -150,19 +150,22 @@ def respond_with_selection_ranges(uri, positions)
sig { params(uri: String).returns(LanguageServer::Protocol::Interface::SemanticTokens) }
def respond_with_semantic_highlighting(uri)
store.cache_fetch(uri, :semantic_highlighting) do |document|
Requests::SemanticHighlighting.new(document, encoder: Requests::Support::SemanticTokenEncoder.new).run
T.cast(
Requests::SemanticHighlighting.new(document, encoder: Requests::Support::SemanticTokenEncoder.new).run,
LanguageServer::Protocol::Interface::SemanticTokens
)
end
end

sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
sig { params(uri: String).returns(T.nilable(T::Array[LanguageServer::Protocol::Interface::TextEdit])) }
def respond_with_formatting(uri)
Requests::Formatting.run(uri, store.get(uri))
Requests::Formatting.new(uri, store.get(uri)).run
end

sig { params(uri: String).void }
def send_diagnostics(uri)
response = store.cache_fetch(uri, :diagnostics) do |document|
Requests::Diagnostics.run(uri, document)
Requests::Diagnostics.new(uri, document).run
end

@writer.write(
Expand All @@ -175,11 +178,11 @@ def send_diagnostics(uri)
end

sig do
params(uri: String, range: T::Range[Integer]).returns(T::Array[LanguageServer::Protocol::Interface::Diagnostic])
params(uri: String, range: T::Range[Integer]).returns(T::Array[LanguageServer::Protocol::Interface::CodeAction])
end
def respond_with_code_actions(uri, range)
store.cache_fetch(uri, :code_actions) do |document|
Requests::CodeActions.run(uri, document, range)
Requests::CodeActions.new(uri, document, range).run
end
end

Expand All @@ -190,10 +193,16 @@ def respond_with_code_actions(uri, range)
).returns(T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
end
def respond_with_document_highlight(uri, position)
Requests::DocumentHighlight.run(store.get(uri), position)
Requests::DocumentHighlight.new(store.get(uri), position).run
end

sig { params(request: T::Hash[Symbol, T.untyped], block: T.proc.void).returns(T.untyped) }
sig do
type_parameters(:T)
.params(
request: T::Hash[Symbol, T.untyped],
block: T.proc.returns(T.type_parameter(:T))
).returns(T.type_parameter(:T))
end
def with_telemetry(request, &block)
result = T.let(nil, T.untyped)
error = T.let(nil, T.nilable(StandardError))
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_lsp/requests.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
Expand Down
16 changes: 9 additions & 7 deletions lib/ruby_lsp/requests/base_request.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
module Requests
# :nodoc:
class BaseRequest < SyntaxTree::Visitor
def self.run(document)
new(document).run
end
extend T::Sig
extend T::Helpers

abstract!

sig { params(document: Document).void }
def initialize(document)
@document = document

super()
end

def run
raise NotImplementedError, "#{self.class}#run must be implemented"
end
sig { abstract.returns(Object) }
def run; end

sig { params(node: SyntaxTree::Node).returns(LanguageServer::Protocol::Interface::Range) }
def range_from_syntax_tree_node(node)
loc = node.location

Expand Down
27 changes: 18 additions & 9 deletions lib/ruby_lsp/requests/code_actions.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
Expand All @@ -14,23 +14,32 @@ module Requests
# puts "Hello" # --> code action: quick fix indentation
# end
# ```
class CodeActions
def self.run(uri, document, range)
new(uri, document, range).run
end
class CodeActions < BaseRequest
extend T::Sig

sig do
params(
uri: String,
document: Document,
range: T::Range[Integer]
).void
end
def initialize(uri, document, range)
@document = document
super(document)

@uri = uri
@range = range
end

sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::CodeAction], Object)) }
def run
diagnostics = Diagnostics.run(@uri, @document)
corrections = diagnostics.select { |diagnostic| diagnostic.correctable? && diagnostic.in_range?(@range) }
diagnostics = Diagnostics.new(@uri, @document).run
corrections = diagnostics.select do |diagnostic|
diagnostic.correctable? && T.cast(diagnostic, Support::RuboCopDiagnostic).in_range?(@range)
end
return [] if corrections.empty?

corrections.map!(&:to_lsp_code_action)
T.cast(corrections, T::Array[Support::RuboCopDiagnostic]).map!(&:to_lsp_code_action)
end
end
end
Expand Down
14 changes: 13 additions & 1 deletion lib/ruby_lsp/requests/diagnostics.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
Expand All @@ -15,6 +15,16 @@ module Requests
# end
# ```
class Diagnostics < RuboCopRequest
extend T::Sig

sig do
override.returns(
T.any(
T.all(T::Array[Support::RuboCopDiagnostic], Object),
T.all(T::Array[Support::SyntaxErrorDiagnostic], Object),
)
)
end
def run
return syntax_error_diagnostics if @document.syntax_errors?

Expand All @@ -23,12 +33,14 @@ def run
@diagnostics
end

sig { params(_file: String, offenses: T::Array[RuboCop::Cop::Offense]).void }
def file_finished(_file, offenses)
@diagnostics = offenses.map { |offense| Support::RuboCopDiagnostic.new(offense, @uri) }
end

private

sig { returns(T::Array[Support::SyntaxErrorDiagnostic]) }
def syntax_error_diagnostics
@document.syntax_error_edits.map { |e| Support::SyntaxErrorDiagnostic.new(e) }
end
Expand Down
27 changes: 21 additions & 6 deletions lib/ruby_lsp/requests/document_highlight.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: true
# typed: strict
# frozen_string_literal: true

module RubyLsp
Expand All @@ -21,18 +21,28 @@ module Requests
# end
# ```
class DocumentHighlight < BaseRequest
def self.run(document, position)
new(document, position).run
extend T::Sig

VarNodes = T.type_alias do
T.any(
SyntaxTree::GVar,
SyntaxTree::Ident,
SyntaxTree::IVar,
SyntaxTree::Const,
SyntaxTree::CVar
)
end

sig { params(document: Document, position: Document::PositionShape).void }
def initialize(document, position)
@highlights = []
@highlights = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
position = Document::Scanner.new(document.source).find_position(position)
@target = find(document.tree, position)
@target = T.let(find(document.tree, position), T.nilable(VarNodes))

super(document)
end

sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::DocumentHighlight], Object)) }
def run
# no @target means the target is not highlightable
return [] unless @target
Expand All @@ -41,6 +51,7 @@ def run
@highlights
end

sig { params(node: SyntaxTree::VarField).void }
def visit_var_field(node)
if matches_target?(node.value)
add_highlight(
Expand All @@ -52,6 +63,7 @@ def visit_var_field(node)
super
end

sig { params(node: SyntaxTree::VarRef).void }
def visit_var_ref(node)
if matches_target?(node.value)
add_highlight(
Expand All @@ -65,6 +77,7 @@ def visit_var_ref(node)

private

sig { params(node: SyntaxTree::Node, position: Integer).returns(T.nilable(VarNodes)) }
def find(node, position)
matched =
node.child_nodes.compact.bsearch do |child|
Expand All @@ -83,10 +96,12 @@ def find(node, position)
end
end

sig { params(node: SyntaxTree::Node).returns(T::Boolean) }
def matches_target?(node)
node.is_a?(@target.class) && node.value == @target.value
node.is_a?(@target.class) && T.cast(node, VarNodes).value == T.must(@target).value
end

sig { params(node: SyntaxTree::Node, kind: Integer).void }
def add_highlight(node, kind)
range = range_from_syntax_tree_node(node)
@highlights << LanguageServer::Protocol::Interface::DocumentHighlight.new(range: range, kind: kind)
Expand Down
Loading