diff --git a/.gitignore b/.gitignore index 5e8900e..5d5a18c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ /tmp/ /vendor/bundle/ /node_modules/ +/.rubocop-* diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..59497f4 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,45 @@ +inherit_from: + - https://github.com/onk/onkcop/raw/v0.51.0.0/config/rubocop.yml + +AllCops: + TargetRubyVersion: 2.2 + Exclude: + - 'bin/**/*' + +# TODO: Remove this config after droping Ruby 2.2 support +Layout/IndentHeredoc: + Include: + - 'test/**/*' + +Lint/AssignmentInCondition: + Enabled: false + +Lint/HandleExceptions: + Enabled: false + +Naming/HeredocDelimiterNaming: + Enabled: false + +Style/BlockDelimiters: + Enabled: false + +Style/MultilineBlockChain: + Enabled: false + +Style/Semicolon: + Enabled: false + +Metrics/AbcSize: + Max: 50 + +Metrics/BlockLength: + Max: 30 + +Metrics/MethodLength: + Max: 40 + +Metrics/ModuleLength: + Enabled: false + +Metrics/LineLength: + Max: 200 diff --git a/Gemfile b/Gemfile index 8fbd55c..1a9efaa 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ -source 'https://rubygems.org' +source "https://rubygems.org" # Specify your gem's dependencies in language_server.gemspec gemspec # TODO: Use released gem after new release includes https://github.com/bbatsov/rubocop/pull/4987 -gem 'rubocop', git: 'https://github.com/bbatsov/rubocop' +gem "rubocop", git: "https://github.com/bbatsov/rubocop" diff --git a/Guardfile b/Guardfile index 4b43f34..890a941 100644 --- a/Guardfile +++ b/Guardfile @@ -5,5 +5,5 @@ guard :minitest, all_after_pass: true do watch(%r{^test/(.*)\/?test_(.*)\.rb$}) watch(%r{^test/(.*)\/?(.*)_test\.rb$}) watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" } - watch(%r{^test/test_helper\.rb$}) { 'test' } + watch(%r{^test/test_helper\.rb$}) { "test" } end diff --git a/Rakefile b/Rakefile index d6c5113..d433a1e 100644 --- a/Rakefile +++ b/Rakefile @@ -4,7 +4,7 @@ require "rake/testtask" Rake::TestTask.new(:test) do |t| t.libs << "test" t.libs << "lib" - t.test_files = FileList['test/**/*_test.rb'] + t.test_files = FileList["test/**/*_test.rb"] end task :default => :test diff --git a/benchmark/rubocop b/benchmark/rubocop index 058dd16..ee788c7 100755 --- a/benchmark/rubocop +++ b/benchmark/rubocop @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -require 'bundler/setup' -require 'benchmark/ips' -require 'language_server' +require "bundler/setup" +require "benchmark/ips" +require "language_server" error_code = <<-EOS require "foo @@ -13,7 +13,7 @@ a = 1 EOS valid_code = File.read(__FILE__) -require 'pry-byebug' +require "pry-byebug" LanguageServer::Linter::Rubocop.new(valid_code).call Benchmark.ips do |x| diff --git a/benchmark/ruby_wc b/benchmark/ruby_wc index 8191a61..5a16a7f 100755 --- a/benchmark/ruby_wc +++ b/benchmark/ruby_wc @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -require 'bundler/setup' -require 'benchmark/ips' -require 'language_server' +require "bundler/setup" +require "benchmark/ips" +require "language_server" error_code = <<-EOS require "foo diff --git a/bin/ci b/bin/ci new file mode 100755 index 0000000..f388e78 --- /dev/null +++ b/bin/ci @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +set -ex + +bin/setup +bin/rubocop +bin/m diff --git a/bin/rubocop b/bin/rubocop new file mode 100755 index 0000000..ccb4d56 --- /dev/null +++ b/bin/rubocop @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true +# +# This file was generated by Bundler. +# +# The application 'rubocop' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rubocop", "rubocop") diff --git a/circle.yml b/circle.yml index 4007e84..d43f0c6 100644 --- a/circle.yml +++ b/circle.yml @@ -20,8 +20,7 @@ jobs: docker cp . project:/app docker start project docker-compose build $SERVICE_NAME - - run: docker-compose run $SERVICE_NAME bin/setup - - run: docker-compose run $SERVICE_NAME bin/m + - run: docker-compose run $SERVICE_NAME bin/ci test-2-3: <<: *test docker: diff --git a/language_server.gemspec b/language_server.gemspec index 74e2876..58b4248 100644 --- a/language_server.gemspec +++ b/language_server.gemspec @@ -1,7 +1,7 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) + +lib = File.expand_path("../lib", __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'language_server/version' +require "language_server/version" Gem::Specification.new do |spec| spec.name = "language_server" @@ -9,8 +9,8 @@ Gem::Specification.new do |spec| spec.authors = ["Fumiaki MATSUSHIMA"] spec.email = ["mtsmfm@gmail.com"] - spec.summary = %q{A Ruby Language Server implementation} - spec.description = %q{A Ruby Language Server implementation} + spec.summary = "A Ruby Language Server implementation" + spec.description = "A Ruby Language Server implementation" spec.homepage = "https://github.com/mtsmfm/language_server-ruby" spec.license = "MIT" @@ -19,24 +19,24 @@ Gem::Specification.new do |spec| f.match(%r{^(test|spec|features)/}) end rescue - Dir.glob("**/*").reject {|path| File.directory?(path) } + Dir.glob("**/*").reject { |path| File.directory?(path) } end spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "rcodetools" spec.add_dependency "language_server-protocol", "0.4.0" + spec.add_dependency "rcodetools" + spec.add_development_dependency "awesome_print" + spec.add_development_dependency "benchmark-ips" spec.add_development_dependency "bundler", "~> 1.14" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "minitest", "~> 5.0" spec.add_development_dependency "guard" spec.add_development_dependency "guard-minitest" + spec.add_development_dependency "m" + spec.add_development_dependency "minitest", "~> 5.0" spec.add_development_dependency "minitest-color" - spec.add_development_dependency "pry-byebug" spec.add_development_dependency "minitest-power_assert" - spec.add_development_dependency "m" - spec.add_development_dependency "awesome_print" - spec.add_development_dependency "benchmark-ips" + spec.add_development_dependency "pry-byebug" + spec.add_development_dependency "rake", "~> 10.0" end diff --git a/lib/language_server.rb b/lib/language_server.rb index 59db621..3d36dc1 100644 --- a/lib/language_server.rb +++ b/lib/language_server.rb @@ -37,16 +37,14 @@ def notify(method:, params: {}) method = request[:method].to_sym - _, subscriber = subscribers.find {|k, _| - k === method - } + subscriber = subscribers[method] if subscriber keys = subscriber.parameters.map(&:last) result = subscriber.call( { request: request, notifier: writer.method(:notify), variables: variables - }.merge(variables).select {|k, _| keys.include?(k) } + }.merge(variables).select { |k, _| keys.include?(k) }, ) if request[:id] @@ -74,14 +72,14 @@ def on(method, &callback) Protocol::Interface::InitializeResult.new( capabilities: Protocol::Interface::ServerCapabilities.new( text_document_sync: Protocol::Interface::TextDocumentSyncOptions.new( - change: Protocol::Constant::TextDocumentSyncKind::FULL + change: Protocol::Constant::TextDocumentSyncKind::FULL, ), completion_provider: Protocol::Interface::CompletionOptions.new( resolve_provider: true, - trigger_characters: %w(.) + trigger_characters: %w[.], ), - definition_provider: true - ) + definition_provider: true, + ), ) end @@ -103,13 +101,13 @@ def on(method, &callback) range: Protocol::Interface::Range.new( start: Protocol::Interface::Position.new( line: error.line_num, - character: 0 + character: 0, ), end: Protocol::Interface::Position.new( line: error.line_num, - character: 0 - ) - ) + character: 0, + ), + ), ) end @@ -117,8 +115,8 @@ def on(method, &callback) method: :"textDocument/publishDiagnostics", params: Protocol::Interface::PublishDiagnosticsParams.new( uri: uri, - diagnostics: diagnostics - ) + diagnostics: diagnostics, + ), ) end @@ -128,7 +126,7 @@ def on(method, &callback) [ CompletionProvider::AdHoc.new(uri: uri, line: line, character: character, project: project), - CompletionProvider::Rcodetools.new(uri: uri, line: line, character: character, file_store: file_store) + CompletionProvider::Rcodetools.new(uri: uri, line: line, character: character, file_store: file_store), ].flat_map(&:call) end diff --git a/lib/language_server/completion_provider/ad_hoc.rb b/lib/language_server/completion_provider/ad_hoc.rb index d0e55dd..bdcb0a2 100644 --- a/lib/language_server/completion_provider/ad_hoc.rb +++ b/lib/language_server/completion_provider/ad_hoc.rb @@ -11,35 +11,35 @@ def initialize(uri:, line:, character:, project:) end def call - (project.constants(uri: uri, line: line, character: character).map {|c| + (project.constants(uri: uri, line: line, character: character).map { |c| Protocol::Interface::CompletionItem.new( label: c.name, detail: c.full_name, documentation: "#{c.remote_path}##{c.lineno}", - kind: Protocol::Constant::CompletionItemKind::ENUM + kind: Protocol::Constant::CompletionItemKind::ENUM, ) } + - project.classes(uri: uri, line: line, character: character).map {|c| + project.classes(uri: uri, line: line, character: character).map { |c| Protocol::Interface::CompletionItem.new( label: c.name, detail: c.full_name, documentation: "#{c.remote_path}##{c.lineno}", - kind: Protocol::Constant::CompletionItemKind::CLASS + kind: Protocol::Constant::CompletionItemKind::CLASS, ) } + - project.modules(uri: uri, line: line, character: character).map {|m| + project.modules(uri: uri, line: line, character: character).map { |m| Protocol::Interface::CompletionItem.new( label: m.name, detail: m.full_name, documentation: "#{m.remote_path}##{m.lineno}", - kind: Protocol::Constant::CompletionItemKind::MODULE + kind: Protocol::Constant::CompletionItemKind::MODULE, ) }).uniq(&:label) end private - attr_reader :uri, :line, :character, :project + attr_reader :uri, :line, :character, :project end end end diff --git a/lib/language_server/completion_provider/rcodetools.rb b/lib/language_server/completion_provider/rcodetools.rb index 1cdaaf3..afbcbbf 100644 --- a/lib/language_server/completion_provider/rcodetools.rb +++ b/lib/language_server/completion_provider/rcodetools.rb @@ -28,16 +28,16 @@ def call Protocol::Interface::CompletionItem.new( label: method_name, detail: description, - kind: Protocol::Constant::CompletionItemKind::METHOD + kind: Protocol::Constant::CompletionItemKind::METHOD, ) end end private - def source - @file_store.read_remote_uri(@uri) - end + def source + @file_store.read_remote_uri(@uri) + end end end end diff --git a/lib/language_server/definition_provider/ad_hoc.rb b/lib/language_server/definition_provider/ad_hoc.rb index 0c86d1a..1116109 100644 --- a/lib/language_server/definition_provider/ad_hoc.rb +++ b/lib/language_server/definition_provider/ad_hoc.rb @@ -15,20 +15,20 @@ def call range: Protocol::Interface::Range.new( start: Protocol::Interface::Position.new( line: n.lines.begin, - character: 0 + character: 0, ), end: Protocol::Interface::Position.new( line: n.lines.end, - character: 0 - ) - ) + character: 0, + ), + ), ) end end private - attr_reader :uri, :line, :character, :project + attr_reader :uri, :line, :character, :project end end end diff --git a/lib/language_server/file_store.rb b/lib/language_server/file_store.rb index e956458..696f739 100644 --- a/lib/language_server/file_store.rb +++ b/lib/language_server/file_store.rb @@ -64,36 +64,36 @@ def read_remote_uri(remote_uri) def each(&block) all_paths.each do |path| - block.call(read(path), path) + yield(read(path), path) end end private - attr_reader :load_paths, :remote_root, :local_root + attr_reader :load_paths, :remote_root, :local_root - def all_paths - (cache_store.keys + load_paths.flat_map {|path| - Dir.glob(File.join(path, "**", "*.rb")) - }.map {|path| - FilePath.new(local_root: local_root, remote_root: remote_root, local_path: path) - }).uniq - end + def all_paths + (cache_store.keys + load_paths.flat_map { |path| + Dir.glob(File.join(path, "**", "*.rb")) + }.map { |path| + FilePath.new(local_root: local_root, remote_root: remote_root, local_path: path) + }).uniq + end - def exists_on_cache?(path) - cache_store.key?(path) - end + def exists_on_cache?(path) + cache_store.has_key?(path) + end - def read_from_cache(path) - cache_store[path] - end + def read_from_cache(path) + cache_store[path] + end - def read_from_local(path) - File.read(path.local_path) - end + def read_from_local(path) + File.read(path.local_path) + end - def cache_store - @cache_store ||= {} - end + def cache_store + @cache_store ||= {} + end end end diff --git a/lib/language_server/linter/rubocop.rb b/lib/language_server/linter/rubocop.rb index ccbeb18..897c67e 100644 --- a/lib/language_server/linter/rubocop.rb +++ b/lib/language_server/linter/rubocop.rb @@ -1,22 +1,21 @@ begin - require 'rubocop' + require "rubocop" rescue LoadError end module LanguageServer module Linter class Rubocop - def initialize(source, config_path="") + def initialize(source, config_path = "") @source = source @config_path = config_path end - def call return [] unless defined? ::RuboCop args = [] - args += ["--config", @config_path] if @config_path != '' - args += ["--format", "json","--stdin", "lsp_buffer.rb"] + args += ["--config", @config_path] if @config_path != "" + args += ["--format", "json", "--stdin", "lsp_buffer.rb"] o = nil begin $stdin = StringIO.new(@source) @@ -32,24 +31,23 @@ def call $stdout = STDOUT end return [] unless o - JSON - .parse(o)['files'].map { |v| v['offenses'] } - .flatten - .map { |v| Error.new(line_num: v['location']['line'].to_i - 1, message: v['message'], type: convert_type(v['severity'])) } + JSON. + parse(o)["files"].map { |v| v["offenses"] }. + flatten. + map { |v| Error.new(line_num: v["location"]["line"].to_i - 1, message: v["message"], type: convert_type(v["severity"])) } end private - def convert_type(type) - case type - when 'refactor' then 'warning' - when 'convention' then 'warning' - when 'warning' then 'warning' - when 'error' then 'error' - when 'fatal' then 'error' + def convert_type(type) + case type + when "refactor" then "warning" + when "convention" then "warning" + when "warning" then "warning" + when "error" then "error" + when "fatal" then "error" + end end - end - end end end diff --git a/lib/language_server/linter/ruby_wc.rb b/lib/language_server/linter/ruby_wc.rb index 9588c4a..dfcfa56 100644 --- a/lib/language_server/linter/ruby_wc.rb +++ b/lib/language_server/linter/ruby_wc.rb @@ -26,55 +26,55 @@ def initialize(source) end def call - error_message.scan(/.+:(\d+):\s*(.+?)[,:]\s(.+)/).map do |line_num, type, message| + error_message.scan(/.+:(\d+):\s*(.+?)[,:]\s(.+)/).map do |line_num, type, message| Error.new(line_num: line_num.to_i - 1, message: message, type: type) end end private - # Since Ruby 2.4, syntax error information is outputted to Exception#message instead of stderr - if begin; stderr = $stderr; $stderr = StringIO.new; RubyVM::InstructionSequence.compile('='); rescue SyntaxError => e; e.message != 'compile error'; ensure; $stderr = stderr; end - def error_message - with_verbose do - begin - capture_stderr { RubyVM::InstructionSequence.compile(@source) } - rescue SyntaxError => e - e.message + # Since Ruby 2.4, syntax error information is outputted to Exception#message instead of stderr + if begin; stderr = $stderr; $stderr = StringIO.new; RubyVM::InstructionSequence.compile("="); rescue SyntaxError => e; e.message != "compile error"; ensure; $stderr = stderr; end + def error_message + with_verbose do + begin + capture_stderr { RubyVM::InstructionSequence.compile(@source) } + rescue SyntaxError => e + e.message + end end end - end - else - def error_message - with_verbose do - capture_stderr do - begin - RubyVM::InstructionSequence.compile(@source) - rescue SyntaxError + else + def error_message + with_verbose do + capture_stderr do + begin + RubyVM::InstructionSequence.compile(@source) + rescue SyntaxError + end end end end end - end - def with_verbose - origin = $VERBOSE - $VERBOSE = true - yield - ensure - $VERBOSE = origin - end + def with_verbose + origin = $VERBOSE + $VERBOSE = true + yield + ensure + $VERBOSE = origin + end - def capture_stderr - origin = $stderr - $stderr = StringIO.new + def capture_stderr + origin = $stderr + $stderr = StringIO.new - yield + yield - $stderr.string - ensure - $stderr = origin - end + $stderr.string + ensure + $stderr = origin + end end end end diff --git a/lib/language_server/logger.rb b/lib/language_server/logger.rb index e2793ca..936e671 100644 --- a/lib/language_server/logger.rb +++ b/lib/language_server/logger.rb @@ -1,4 +1,4 @@ -require 'logger' +require "logger" module LanguageServer class << self @@ -8,16 +8,16 @@ def logger end class Formatter - RESET = "\e[0m" - RED = "\e[31m" - YELLOW = "\e[33m" + RESET = "\e[0m".freeze + RED = "\e[31m".freeze + YELLOW = "\e[33m".freeze def call(severity, *rest) msg = default_message(severity, *rest) case severity - when 'ERROR' + when "ERROR" RED + msg + RESET - when 'WARN' + when "WARN" YELLOW + msg + RESET else msg @@ -26,12 +26,12 @@ def call(severity, *rest) private - def default_message(*args) - default_formatter.call(*args) - end + def default_message(*args) + default_formatter.call(*args) + end - def default_formatter - @default_formatter ||= ::Logger::Formatter.new - end + def default_formatter + @default_formatter ||= ::Logger::Formatter.new + end end end diff --git a/lib/language_server/project.rb b/lib/language_server/project.rb index 8779cd3..3d91974 100644 --- a/lib/language_server/project.rb +++ b/lib/language_server/project.rb @@ -1,4 +1,4 @@ -require 'language_server/project/parser' +require "language_server/project/parser" module LanguageServer class Project @@ -12,11 +12,11 @@ def initialize(file_store) def find_definitions(uri:, line:, character:) result = result_store[file_store.path_from_remote_uri(uri)] - ref = result.refs.select {|node| node.lines.include?(line) && node.characters.include?(character) }.min_by {|node| node.characters.size } + ref = result.refs.select { |node| node.lines.include?(line) && node.characters.include?(character) }.min_by { |node| node.characters.size } return [] unless ref - lazy_modules.select {|n| n.full_name == ref.full_name }.force + lazy_classes.select {|n| n.full_name == ref.full_name }.force + lazy_modules.select { |n| n.full_name == ref.full_name }.force + lazy_classes.select { |n| n.full_name == ref.full_name }.force end def recalculate_result(uri) @@ -27,58 +27,58 @@ def recalculate_result(uri) def constants(uri: nil, line: nil, character: nil) node = find_nearest_node(uri: uri, line: line, character: character) if uri && line && character - lazy_constants.select {|n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force + lazy_constants.select { |n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force end def modules(uri: nil, line: nil, character: nil) node = find_nearest_node(uri: uri, line: line, character: character) if uri && line && character - lazy_modules.select {|n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force + lazy_modules.select { |n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force end def classes(uri: nil, line: nil, character: nil) node = find_nearest_node(uri: uri, line: line, character: character) if uri && line && character - lazy_classes.select {|n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force + lazy_classes.select { |n| n.names[0..-2] == Array(node && node.names).first(n.names.size - 1) }.force end private - attr_reader :file_store, :result_store + attr_reader :file_store, :result_store - def lazy_constants - result_store.each_value.lazy.flat_map(&:constants) - end - - def lazy_modules - result_store.each_value.lazy.flat_map(&:modules) - end + def lazy_constants + result_store.each_value.lazy.flat_map(&:constants) + end - def lazy_classes - result_store.each_value.lazy.flat_map(&:classes) - end + def lazy_modules + result_store.each_value.lazy.flat_map(&:modules) + end - def fetch_result - file_store.each {|content, path| - calculate(content, path) - } - end + def lazy_classes + result_store.each_value.lazy.flat_map(&:classes) + end - def find_nearest_node(uri:, line:, character:) - result = result_store[file_store.path_from_remote_uri(uri)] + def fetch_result + file_store.each { |content, path| + calculate(content, path) + } + end - (result.modules + result.classes).select {|node| node.lines.include?(line) }.min_by {|node| node.lines.size } - end + def find_nearest_node(uri:, line:, character:) + result = result_store[file_store.path_from_remote_uri(uri)] - def calculate(content, path) - begin - result = Parser.parse(content, path) - rescue => e - LanguageServer.logger.warn("Parse failed (local: #{path.local_path}, remote: #{path.remote_path})") - LanguageServer.logger.warn(e) + (result.modules + result.classes).select { |node| node.lines.include?(line) }.min_by { |node| node.lines.size } end - result_store[path] = result if result - end + def calculate(content, path) + begin + result = Parser.parse(content, path) + rescue => e + LanguageServer.logger.warn("Parse failed (local: #{path.local_path}, remote: #{path.remote_path})") + LanguageServer.logger.warn(e) + end + + result_store[path] = result if result + end end end diff --git a/lib/language_server/project/node.rb b/lib/language_server/project/node.rb index b6f9222..fbae995 100644 --- a/lib/language_server/project/node.rb +++ b/lib/language_server/project/node.rb @@ -6,12 +6,10 @@ def attributes(*attrs) attr_accessor(*attrs) attribute_names.concat(attrs) class_eval <<-RUBY, __FILE__, __LINE__ -def initialize(#{attribute_names.map {|n| "#{n}:" }.join(',')}) - #{ - attribute_names.map {|n| +def initialize(#{attribute_names.map { |n| "#{n}:" }.join(",")}) + #{attribute_names.map { |n| "@#{n} = #{n}" - }.join("\n") - } + }.join("\n")} end RUBY end @@ -23,8 +21,13 @@ def attribute_names attributes :lineno, :character, :path - def remote_path; path.remote_path; end - def local_path; path.local_path; end + def remote_path + path.remote_path + end + + def local_path + path.local_path + end def eql?(other) other.instance_of?(self.class) && attributes == other.attributes @@ -39,7 +42,7 @@ def hash end def attributes - self.class.attribute_names.map {|a| + self.class.attribute_names.map { |a| [a, public_send(a)] }.to_h end @@ -57,7 +60,7 @@ def names end def full_name - names.join('::') + names.join("::") end end @@ -68,7 +71,7 @@ class LiteralValue < Node class Module < Node attributes :constant, :children - %i(name namespaces full_name names).each do |m| + %i[name namespaces full_name names].each do |m| define_method(m) { constant.__send__(m) } end @@ -117,7 +120,7 @@ def name end def full_name - names.join('::') + names.join("::") end def inspect @@ -149,7 +152,7 @@ def names end def full_name - names.join('::') + names.join("::") end def inspect diff --git a/lib/language_server/project/parser.rb b/lib/language_server/project/parser.rb index 8e1de01..03d58d5 100644 --- a/lib/language_server/project/parser.rb +++ b/lib/language_server/project/parser.rb @@ -1,5 +1,5 @@ -require 'language_server/project/node' -require 'ripper' +require "language_server/project/node" +require "ripper" module LanguageServer class Project @@ -32,79 +32,79 @@ def initialize(src, path) private - alias character column + alias_method :character, :column - attr_reader :path + attr_reader :path - def lineno - # Language Server Protocol's lineno is zero origin - super - 1 - end + def lineno + # Language Server Protocol's lineno is zero origin + super - 1 + end - def on_var_ref(node) - if node.instance_of?(Constant) - build_node(VarRef, node: node).tap do |n| - result.refs << n + def on_var_ref(node) + if node.instance_of?(Constant) + build_node(VarRef, node: node).tap do |n| + result.refs << n + end + else + node end - else - node end - end - def on_const_path_ref(*nodes) - if nodes.all? {|n| [Constant, ConstPathRef, VarRef].include?(n.class) } - build_node(ConstPathRef, nodes: nodes).tap do |n| - result.refs << n + def on_const_path_ref(*nodes) + if nodes.all? { |n| [Constant, ConstPathRef, VarRef].include?(n.class) } + build_node(ConstPathRef, nodes: nodes).tap do |n| + result.refs << n + end + else + nodes end - else - nodes end - end - def on_const(name) - build_node(Constant, namespaces: [], name: name, value: nil) - end + def on_const(name) + build_node(Constant, namespaces: [], name: name, value: nil) + end - def on_def(*args) - args.flatten.compact - end + def on_def(*args) + args.flatten.compact + end - def on_int(value) - build_node(LiteralValue, value: value.to_i) - end + def on_int(value) + build_node(LiteralValue, value: value.to_i) + end - def on_stmts_add(*args) - args.flatten.compact - end + def on_stmts_add(*args) + args.flatten.compact + end - def on_assign(left, right) - result.constants << left if Constant === left + def on_assign(left, right) + result.constants << left if left.instance_of?(Constant) - left.value = right if left.respond_to?(:value) # TODO: remove this condition - left - end + left.value = right if left.respond_to?(:value) # TODO: remove this condition + left + end - def on_module(constant, children) - cn = children.select {|child| child.respond_to?(:unshift_namespace) } + def on_module(constant, children) + cn = children.select { |child| child.respond_to?(:unshift_namespace) } - build_node(Module, constant: constant, children: cn).tap do |m| - result.modules << m - cn.each {|child| child.unshift_namespace(m) } + build_node(Module, constant: constant, children: cn).tap do |m| + result.modules << m + cn.each { |child| child.unshift_namespace(m) } + end end - end - def on_class(constant, superclass, children) - cn = children.select {|child| child.respond_to?(:unshift_namespace) } + def on_class(constant, superclass, children) + cn = children.select { |child| child.respond_to?(:unshift_namespace) } - build_node(Class, constant: constant, superclass: superclass, children: cn).tap do |c| - result.classes << c - cn.each {|child| child.unshift_namespace(c) } + build_node(Class, constant: constant, superclass: superclass, children: cn).tap do |c| + result.classes << c + cn.each { |child| child.unshift_namespace(c) } + end end - end - def build_node(klass, **args) - klass.new({lineno: lineno, character: character, path: path}.merge(args)) - end + def build_node(klass, **args) + klass.new({ lineno: lineno, character: character, path: path }.merge(args)) + end end end end diff --git a/lib/language_server/version.rb b/lib/language_server/version.rb index 7f17d09..9ed2a74 100644 --- a/lib/language_server/version.rb +++ b/lib/language_server/version.rb @@ -1,3 +1,3 @@ module LanguageServer - VERSION = "0.9.0" + VERSION = "0.9.0".freeze end diff --git a/test/language_server/completion_provider/rcodetools_test.rb b/test/language_server/completion_provider/rcodetools_test.rb index a0c8332..bbd899a 100644 --- a/test/language_server/completion_provider/rcodetools_test.rb +++ b/test/language_server/completion_provider/rcodetools_test.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require "test_helper" module LanguageServer module CompletionProvider @@ -18,7 +18,7 @@ def test_array candidates = [ Protocol::Interface::CompletionItem.new(label: "last", kind: Protocol::Constant::CompletionItemKind::METHOD, detail: "Array#last"), Protocol::Interface::CompletionItem.new(label: "lazy", kind: Protocol::Constant::CompletionItemKind::METHOD, detail: "Enumerable#lazy"), - Protocol::Interface::CompletionItem.new(label: "length", kind: Protocol::Constant::CompletionItemKind::METHOD, detail: "Array#length") + Protocol::Interface::CompletionItem.new(label: "length", kind: Protocol::Constant::CompletionItemKind::METHOD, detail: "Array#length"), ] assert { provider.call.to_json == candidates.to_json } diff --git a/test/language_server/linter/rubocop_test.rb b/test/language_server/linter/rubocop_test.rb index 6673ca5..0154682 100644 --- a/test/language_server/linter/rubocop_test.rb +++ b/test/language_server/linter/rubocop_test.rb @@ -1,9 +1,9 @@ -require 'test_helper' +require "test_helper" module LanguageServer::Linter class RubocopTest < Minitest::Test def setup - @config_path = File.expand_path('./../../../fixtures/rubocop.yml', __FILE__) + @config_path = File.expand_path("./../../../fixtures/rubocop.yml", __FILE__) end def test_fatal_error @@ -14,8 +14,8 @@ def test_fatal_error Error.new( line_num: 0, message: "unterminated string meets end of file\n(Using Ruby 2.1 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", - type: 'error' - ) + type: "error", + ), ] end end @@ -24,7 +24,7 @@ def test_warning_error source = "a = 'a'" actual = Rubocop.new(source, @config_path).call assert do - actual.first == Error.new(line_num: 0, message: "Useless assignment to variable - `a`.", type: 'warning') + actual.first == Error.new(line_num: 0, message: "Useless assignment to variable - `a`.", type: "warning") end end @@ -32,7 +32,7 @@ def test_convention_error source = 'require "foo"' actual = Rubocop.new(source, @config_path).call assert do - actual.first == Error.new(line_num: 0, message: "Prefer single-quoted strings when you don't need string interpolation or special symbols.", type: 'warning') + actual.first == Error.new(line_num: 0, message: "Prefer single-quoted strings when you don't need string interpolation or special symbols.", type: "warning") end end end diff --git a/test/language_server/linter/ruby_wc_test.rb b/test/language_server/linter/ruby_wc_test.rb index 67bfb90..7d4208b 100644 --- a/test/language_server/linter/ruby_wc_test.rb +++ b/test/language_server/linter/ruby_wc_test.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require "test_helper" module LanguageServer::Linter class RubyWCTest < Minitest::Test diff --git a/test/language_server/project/parser_test.rb b/test/language_server/project/parser_test.rb index 839935f..6b0ea87 100644 --- a/test/language_server/project/parser_test.rb +++ b/test/language_server/project/parser_test.rb @@ -1,4 +1,4 @@ -require 'test_helper' +require "test_helper" module LanguageServer class Project @@ -10,7 +10,7 @@ def test_toplevel_const result = Parser.parse(body) - assert { result.constants.map(&:full_name) == %w(TOP_LEVEL_CONST) } + assert { result.constants.map(&:full_name) == %w[TOP_LEVEL_CONST] } end def test_const_within_class_and_module @@ -24,8 +24,8 @@ module Mod result = Parser.parse(body) - assert { result.modules.map(&:full_name) == %w(Cls::Mod) } - assert { result.constants.map(&:full_name) == %w(Cls::Mod::CONST) } + assert { result.modules.map(&:full_name) == %w[Cls::Mod] } + assert { result.constants.map(&:full_name) == %w[Cls::Mod::CONST] } end def test_class @@ -36,7 +36,7 @@ class Hi result = Parser.parse(body) - assert { result.classes.map(&:full_name) == %w(Hi) } + assert { result.classes.map(&:full_name) == %w[Hi] } end def test_module @@ -47,7 +47,7 @@ module Hi result = Parser.parse(body) - assert { result.modules.map(&:full_name) == %w(Hi) } + assert { result.modules.map(&:full_name) == %w[Hi] } end def test_module_with_method @@ -60,7 +60,7 @@ def initialize result = Parser.parse(body) - assert { result.modules.map(&:full_name) == %w(Hi) } + assert { result.modules.map(&:full_name) == %w[Hi] } end def test_ref @@ -68,7 +68,7 @@ def test_ref A EOS - assert { result.refs.map {|r| [r.full_name, r.characters] } == [['A', 0..1]] } + assert { result.refs.map { |r| [r.full_name, r.characters] } == [["A", 0..1]] } end def test_ref_2 @@ -76,7 +76,7 @@ def test_ref_2 A::B EOS - assert { result.refs.map {|r| [r.full_name, r.characters] } == [['A', 0..2], ['A::B', 0..3]] } + assert { result.refs.map { |r| [r.full_name, r.characters] } == [["A", 0..2], ["A::B", 0..3]] } end def test_ref_3 @@ -84,7 +84,7 @@ def test_ref_3 A::B::C EOS - assert { result.refs.map {|r| [r.full_name, r.characters] } == [['A', 0..2], ['A::B', 0..3], ['A::B::C', 0..6]] } + assert { result.refs.map { |r| [r.full_name, r.characters] } == [["A", 0..2], ["A::B", 0..3], ["A::B::C", 0..6]] } end def test_ref_within_module @@ -94,7 +94,7 @@ module A end EOS - assert { result.refs.map {|r| [r.full_name, r.characters] } == [['A::B', 2..3]] } + assert { result.refs.map { |r| [r.full_name, r.characters] } == [["A::B", 2..3]] } result = Parser.parse(<<-EOS.strip_heredoc) module A @@ -102,7 +102,7 @@ module A end EOS - assert { result.refs.map {|r| [r.full_name, r.characters] } == [['A::B', 2..4], ['A::B::C', 2..5]] } + assert { result.refs.map { |r| [r.full_name, r.characters] } == [["A::B", 2..4], ["A::B::C", 2..5]] } end def test_const_ref_with_method @@ -123,7 +123,7 @@ class C::D::E end EOS - assert { result.classes.map(&:full_name) == %w(A::B::C::D::E) } + assert { result.classes.map(&:full_name) == %w[A::B::C::D::E] } end end end diff --git a/test/language_server/project_test.rb b/test/language_server/project_test.rb index ca7cf39..42c971c 100644 --- a/test/language_server/project_test.rb +++ b/test/language_server/project_test.rb @@ -1,10 +1,10 @@ -require 'test_helper' +require "test_helper" module LanguageServer class ProjectTest < Minitest::Test def test_const_within_class_and_module store = FileStore.new - store.cache('file:///a.rb', <<-EOS.strip_heredoc) + store.cache("file:///a.rb", <<-EOS.strip_heredoc) class A module A class C @@ -13,21 +13,21 @@ class C end EOS - store.cache('file:///b.rb', <<-EOS.strip_heredoc) + store.cache("file:///b.rb", <<-EOS.strip_heredoc) class A module B end end EOS - store.cache('file:///c.rb', <<-EOS.strip_heredoc) + store.cache("file:///c.rb", <<-EOS.strip_heredoc) class B module C end end EOS - uri = 'file:///foo.rb' + uri = "file:///foo.rb" store.cache(uri, <<-EOS.strip_heredoc) class A @@ -40,16 +40,16 @@ def hi project = Project.new(store) assert { project.modules(uri: uri, line: 0, character: 0).map(&:full_name) == [] } - assert { project.modules(uri: uri, line: 1, character: 0).map(&:full_name).uniq.sort == %w(A::A A::B).sort } + assert { project.modules(uri: uri, line: 1, character: 0).map(&:full_name).uniq.sort == %w[A::A A::B].sort } - assert { project.classes(uri: uri, line: 0, character: 0).map(&:full_name).uniq.sort == %w(A B).sort } - assert { project.classes(uri: uri, line: 1, character: 0).map(&:full_name).uniq.sort == %w(A B).sort } - assert { project.classes(uri: uri, line: 2, character: 0).map(&:full_name).uniq.sort == %w(A B A::A::C).sort } + assert { project.classes(uri: uri, line: 0, character: 0).map(&:full_name).uniq.sort == %w[A B].sort } + assert { project.classes(uri: uri, line: 1, character: 0).map(&:full_name).uniq.sort == %w[A B].sort } + assert { project.classes(uri: uri, line: 2, character: 0).map(&:full_name).uniq.sort == %w[A B A::A::C].sort } end def test_find_definition store = FileStore.new - store.cache('file:///a.rb', <<-EOS.strip_heredoc) + store.cache("file:///a.rb", <<-EOS.strip_heredoc) class A module A class C @@ -60,7 +60,7 @@ def foo end EOS - store.cache('file:///b.rb', <<-EOS.strip_heredoc) + store.cache("file:///b.rb", <<-EOS.strip_heredoc) class A def hi A::C.foo @@ -70,8 +70,8 @@ def hi project = Project.new(store) - assert { project.find_definitions(uri: 'file:///b.rb', line: 2, character: 6).first.full_name == 'A::A' } - assert { project.find_definitions(uri: 'file:///b.rb', line: 2, character: 7).first.full_name == 'A::A::C' } + assert { project.find_definitions(uri: "file:///b.rb", line: 2, character: 6).first.full_name == "A::A" } + assert { project.find_definitions(uri: "file:///b.rb", line: 2, character: 7).first.full_name == "A::A::C" } end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 33f3939..17c3ede 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,14 +1,14 @@ -$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) -require 'bundler' +$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) +require "bundler" Bundler.require(:default, :development) -require 'minitest/autorun' -require 'power_assert/colorize' +require "minitest/autorun" +require "power_assert/colorize" class String def strip_heredoc min = scan(/^[ \t]*(?=\S)/).min indent = min ? min.size : 0 - gsub(/^[ \t]{#{indent}}/, '') + gsub(/^[ \t]{#{indent}}/, "") end end