From 9419ca8ae400c381cacb7335b86604fdc07081fc Mon Sep 17 00:00:00 2001 From: Fritz Meissner Date: Mon, 4 Jan 2021 08:12:19 +0200 Subject: [PATCH] Bump version to 0.2.0.pre and update files for name change Gem is now named solargraph-rails, had to change the directory structure for the naming to make sense. --- README.md | 4 +- bin/console | 2 +- lib/solargraph-rails.rb | 32 +++++++ lib/solargraph/rails/files_loader.rb | 16 ++++ lib/solargraph/rails/pin_creator.rb | 88 +++++++++++++++++++ lib/solargraph/rails/ruby_parser.rb | 70 +++++++++++++++ lib/solargraph/rails/version.rb | 5 ++ lib/solargraph_rails.rb | 30 ------- lib/solargraph_rails/files_loader.rb | 14 --- lib/solargraph_rails/pin_creator.rb | 86 ------------------ lib/solargraph_rails/ruby_parser.rb | 68 -------------- lib/solargraph_rails/version.rb | 3 - ..._rails.gemspec => solargraph-rails.gemspec | 17 +--- spec/dynamic_attributes_spec.rb | 6 +- .../rails}/files_loader_spec.rb | 8 +- .../rails}/pin_creator_spec.rb | 36 ++++---- .../rails}/ruby_parser_spec.rb | 30 +++---- spec/solargraph_rails_spec.rb | 4 +- spec/spec_helper.rb | 2 +- 19 files changed, 261 insertions(+), 260 deletions(-) create mode 100644 lib/solargraph-rails.rb create mode 100644 lib/solargraph/rails/files_loader.rb create mode 100644 lib/solargraph/rails/pin_creator.rb create mode 100644 lib/solargraph/rails/ruby_parser.rb create mode 100644 lib/solargraph/rails/version.rb delete mode 100644 lib/solargraph_rails.rb delete mode 100644 lib/solargraph_rails/files_loader.rb delete mode 100644 lib/solargraph_rails/pin_creator.rb delete mode 100644 lib/solargraph_rails/ruby_parser.rb delete mode 100644 lib/solargraph_rails/version.rb rename solargraph_rails.gemspec => solargraph-rails.gemspec (64%) rename spec/lib/{solargraph_rails => solargraph/rails}/files_loader_spec.rb (76%) rename spec/lib/{solargraph_rails => solargraph/rails}/pin_creator_spec.rb (89%) rename spec/lib/{solargraph_rails => solargraph/rails}/ruby_parser_spec.rb (84%) diff --git a/README.md b/README.md index b3ac5d9..2ac8d82 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# SolargraphRails - Help solargraph with Rails +# Solargraph::Rails - Help solargraph with Rails ## Work in progress - here be dragons There are significant rough edges to this gem still. Don't use it if you're not willing to do things like build gems from source and install them locally. See `Installation` below for more info. @@ -84,7 +84,7 @@ plugins: ``` ### Add annotate -Add schema comments your model files using [Annotate](https://github.com/ctran/annotate_models/). At the moment SolargraphRails assumes your schema comments are at the top of the source file. +Add schema comments your model files using [Annotate](https://github.com/ctran/annotate_models/). At the moment Solargraph::Rails assumes your schema comments are at the top of the source file. ## Development diff --git a/bin/console b/bin/console index 81be4f3..8a679f6 100755 --- a/bin/console +++ b/bin/console @@ -1,7 +1,7 @@ #!/usr/bin/env ruby require "bundler/setup" -require "solargraph_rails" +require "solargraph-rails" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. diff --git a/lib/solargraph-rails.rb b/lib/solargraph-rails.rb new file mode 100644 index 0000000..84e8c5b --- /dev/null +++ b/lib/solargraph-rails.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'solargraph' +require 'solargraph/rails/version' +require_relative 'solargraph/rails/pin_creator' +require_relative 'solargraph/rails/ruby_parser' +require_relative 'solargraph/rails/files_loader' + +module Solargraph + module Rails + class DynamicAttributes < Solargraph::Convention::Base + def global yard_map + Solargraph::Environ.new(pins: parse_models) + end + + private + + def parse_models + pins = [] + + FilesLoader.new( + Dir[File.join(Dir.pwd, 'app', 'models', '**', '*.rb')] + ).each { |file, contents| pins.push *PinCreator.new(file, contents).create_pins } + + pins + end + end + end +end + + +Solargraph::Convention.register Solargraph::Rails::DynamicAttributes diff --git a/lib/solargraph/rails/files_loader.rb b/lib/solargraph/rails/files_loader.rb new file mode 100644 index 0000000..51fef22 --- /dev/null +++ b/lib/solargraph/rails/files_loader.rb @@ -0,0 +1,16 @@ +module Solargraph + module Rails + class FilesLoader + def initialize(file_names) + @file_names = file_names + end + + def each(&blk) + @file_names.each do |file_name| + Solargraph::Logging.logger.info "loading from #{file_name}" + blk.call(file_name, File.read(file_name)) + end + end + end + end +end diff --git a/lib/solargraph/rails/pin_creator.rb b/lib/solargraph/rails/pin_creator.rb new file mode 100644 index 0000000..6451b40 --- /dev/null +++ b/lib/solargraph/rails/pin_creator.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +module Solargraph + module Rails + class PinCreator + attr_reader :contents, :path + + def initialize(path, contents) + @path = path + @contents = contents + end + + def create_pins + model_attrs = [] + model_name = nil + module_names = [] + parser = RubyParser.new(file_contents: contents) + + parser.on_comment do |comment| + Solargraph::Logging.logger.info "found comment #{comment}" + col_name, col_type = col_with_type(comment) + if type_translation.keys.include?(col_type) + loc = Solargraph::Location.new( + path, + Solargraph::Range.from_to( + parser.current_line_number, + 0, + parser.current_line_number, + parser.current_line_length - 1 + ) + ) + model_attrs << { name: col_name, type: col_type, location: loc } + else + Solargraph::Logging.logger.info 'could not find annotation in comment' + end + end + + parser.on_module do |mod_name| + Solargraph::Logging.logger.info "found module #{mod_name}" + module_names << mod_name + end + + parser.on_class do |klass, superklass| + Solargraph::Logging.logger.info "found class: #{klass} < #{superklass}" + if ['ActiveRecord::Base', 'ApplicationRecord'].include?(superklass) + model_name = klass + else + Solargraph::Logging.logger.info "Unable to find ActiveRecord model from #{klass} #{superklass}" + model_attrs = [] # don't include anything from this file + end + end + + parser.parse + + Solargraph::Logging.logger.info "Adding #{model_attrs.count} attributes as pins" + model_attrs.map do |attr| + Solargraph::Pin::Method.new( + name: attr[:name], + comments: "@return [#{type_translation[attr[:type]]}]", + location: attr[:location], + closure: Solargraph::Pin::Namespace.new(name: module_names.join('::') + "::#{model_name}"), + scope: :instance, + attribute: true + ) + end + end + + def col_with_type(line) + line + .gsub(/[\(\),:\d]/, '') + .split + .first(2) + end + + def type_translation + { + 'decimal' => 'BigDecimal', + 'integer' => 'Integer', + 'date' => 'Date', + 'datetime' => 'ActiveSupport::TimeWithZone', + 'string' => 'String', + 'boolean' => 'Boolean', + 'text' => 'String' + } + end + end + end +end diff --git a/lib/solargraph/rails/ruby_parser.rb b/lib/solargraph/rails/ruby_parser.rb new file mode 100644 index 0000000..650281f --- /dev/null +++ b/lib/solargraph/rails/ruby_parser.rb @@ -0,0 +1,70 @@ +module Solargraph + module Rails + class RubyParser + attr_reader :current_line_number, :current_line_length + + def initialize(file_contents: '') + @lines = file_contents.lines + @comment_handlers = [] + @class_handlers = [] + @module_handlers = [] + end + + def on_comment(&blk) + @comment_handlers << blk + end + + def on_class(&blk) + @class_handlers << blk + end + + def on_module(&blk) + @module_handlers << blk + end + + def parse + @lines + .map(&:rstrip) + .each_with_index do |line, i| + @current_line_number = i + @current_line_length = line.length + + if is_comment?(line) + comment_content = line.gsub(/#\s*/, '') + @comment_handlers.each { |handler| handler.call(comment_content) } + end + + if is_class?(line) + line.scan(/(?:(? 'BigDecimal', - 'integer' => 'Integer', - 'date' => 'Date', - 'datetime' => 'ActiveSupport::TimeWithZone', - 'string' => 'String', - 'boolean' => 'Boolean', - 'text' => 'String' - } - end - end -end diff --git a/lib/solargraph_rails/ruby_parser.rb b/lib/solargraph_rails/ruby_parser.rb deleted file mode 100644 index 167d6a5..0000000 --- a/lib/solargraph_rails/ruby_parser.rb +++ /dev/null @@ -1,68 +0,0 @@ -module SolargraphRails - class RubyParser - attr_reader :current_line_number, :current_line_length - - def initialize(file_contents: '') - @lines = file_contents.lines - @comment_handlers = [] - @class_handlers = [] - @module_handlers = [] - end - - def on_comment(&blk) - @comment_handlers << blk - end - - def on_class(&blk) - @class_handlers << blk - end - - def on_module(&blk) - @module_handlers << blk - end - - def parse - @lines - .map(&:rstrip) - .each_with_index do |line, i| - @current_line_number = i - @current_line_length = line.length - - if is_comment?(line) - comment_content = line.gsub(/#\s*/, '') - @comment_handlers.each { |handler| handler.call(comment_content) } - end - - if is_class?(line) - line.scan(/(?:(?(x) { } parser.on_comment(&handler) @@ -16,7 +16,7 @@ context 'comments' do it 'passes content of comment without "#"' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "# a comment\n" ) handler = proc { |x| expect(x).to eq('a comment') } @@ -28,7 +28,7 @@ end it 'calls handler once for each comment' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "# a comment\n# another comment\n" ) handler = proc {} @@ -42,7 +42,7 @@ context 'class declaration' do it 'passes correct class name' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class X\nend" ) handler = proc { |klass_name| expect(klass_name).to eq('X') } @@ -54,7 +54,7 @@ end it 'passes class name with superclass' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class X < Y\nend" ) handler = proc do |klass, superklass| @@ -70,7 +70,7 @@ end it 'passes superklass with namespace' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class X < Yabc::Zabc\nend" ) handler = proc do |klass, superklass| @@ -89,7 +89,7 @@ context 'module declaration' do context 'standalone module' do it 'passes correct module name' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "module MyModule\n" ) handler = proc { |mod| expect(mod).to eq('MyModule') } @@ -101,7 +101,7 @@ end it 'calls handler once for each module declaration' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "module MyModule\n module MyModule2\n end\nend" ) handler = proc { } @@ -115,7 +115,7 @@ context 'inline module and class' do it 'calls module handler with inline module name' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class MyModule::MyClass\nend" ) module_handler = proc { |mod| expect(mod).to eq('MyModule') } @@ -128,7 +128,7 @@ end it 'calls class handler with class name' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class MyModule::MyClass\nend" ) class_handler = proc { |klass| expect(klass).to eq('MyClass') } @@ -141,7 +141,7 @@ end it 'multiple inline module names' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class MyModule1::MyModule2::MyModule3::MyClass\nend" ) handler = proc { } @@ -154,7 +154,7 @@ end it 'does not process namespace in superclass' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class MyModule1::MyClass < SuperNamespace::Superclass\nend" ) handler = proc { } @@ -172,7 +172,7 @@ end it 'line info' do - parser = SolargraphRails::RubyParser.new( + parser = Solargraph::Rails::RubyParser.new( file_contents: "class X\n# a comment\n" ) diff --git a/spec/solargraph_rails_spec.rb b/spec/solargraph_rails_spec.rb index 6308712..dd9d69f 100644 --- a/spec/solargraph_rails_spec.rb +++ b/spec/solargraph_rails_spec.rb @@ -1,5 +1,5 @@ -RSpec.describe SolargraphRails do +RSpec.describe Solargraph::Rails do it "has a version number" do - expect(SolargraphRails::VERSION).not_to be nil + expect(Solargraph::Rails::VERSION).not_to be nil end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bce0483..75d67c7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,7 +2,7 @@ require 'bundler/setup' require 'byebug' -require 'solargraph_rails' +require 'solargraph-rails' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure