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

Add rbs types and corresponding lint check #57

Merged
merged 35 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
8c943fb
Add rbs gem
gonzedge Jun 13, 2023
8c2943d
Add all rbs types in sig/
gonzedge Jun 14, 2023
6fd9e83
Fix yardoc comments to match rbs types
gonzedge Jun 14, 2023
1adddfb
Add rbs step to lint
gonzedge Feb 8, 2024
8dc8b0d
Add steep gem and corresponding config
gonzedge Feb 8, 2024
09dc09c
Add type defs for Nodes::Missing and Readers::PlainText
gonzedge Feb 8, 2024
887013b
Add all missing initialize methods to type sigs and remove all "untyp…
gonzedge Feb 8, 2024
31b4b76
Add protected methods to node; fix Array[String] sigs
gonzedge Feb 8, 2024
d45f03d
Add abstract methods so that it does not complain about missing methods
gonzedge Feb 8, 2024
e780f99
Optional block and assignee
gonzedge Feb 8, 2024
763dd7e
Handle nils in compressor
gonzedge Feb 8, 2024
7f33fd1
Add yaml and securerandom libraries to Steepfile
gonzedge Feb 9, 2024
d24a1ac
Add rubyzip types (rubyzip does not have them defined)
gonzedge Feb 9, 2024
5f2e21b
Mark blocks as optional
gonzedge Feb 9, 2024
e721f52
Make TContents for providers nilable
gonzedge Feb 9, 2024
81b313f
Always use Array[String] for chars
gonzedge Feb 9, 2024
815c867
Use steep check for ruby type lint
gonzedge Feb 9, 2024
418766c
Add Container#push signature
gonzedge Feb 19, 2024
3a90ffa
rubocop: Gemfile and Steepfile
gonzedge Feb 20, 2024
528e074
Optional param signature for Rambling:Trie
gonzedge Feb 20, 2024
a6ed027
Add EMPTY_ENUMERATOR constant; use for empty yields
gonzedge Feb 20, 2024
202b766
Add (x || raise) for nil unwrapping
gonzedge Feb 20, 2024
cb09de9
Allow (x || raise) in rubocop
gonzedge Feb 20, 2024
0f6b975
Add racc gem to dev dependencies so that `bundle exec` works locally
gonzedge Feb 25, 2024
ef7c90d
Add missing hash param to `Nodes::Node.initialize` docs
gonzedge Feb 25, 2024
864f8d5
Split pop shift slice
gonzedge Feb 25, 2024
1d32c74
Add abstract methods to Nodes::Node type def
gonzedge Mar 7, 2024
c5a8d26
Rename {,reversed_}char_symbols
gonzedge Mar 7, 2024
daf3b23
Rename Nodes::Raw#add's param {,reversed_}chars for clarity
gonzedge Mar 7, 2024
4e2d4b5
Add explicit `key?` check in `ProviderCollection#resolve`
gonzedge Nov 30, 2024
d277746
Add tests for private abstract methods for 100% coverage
gonzedge Nov 30, 2024
f8ea3b1
Run lint and tests in 3.3.6
gonzedge Nov 30, 2024
f81aa2a
Rubocop correction
gonzedge Nov 30, 2024
6e1e942
Split rubocop and rbs into separate github actions
gonzedge Nov 30, 2024
8001db0
Be more permissive with codeclimate complexity checks
gonzedge Nov 30, 2024
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
7 changes: 6 additions & 1 deletion .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
version: "2"
exclude_patterns:
- 'tasks/'
checks:
method-complexity:
config:
threshold: 7
plugins:
# No to-dos or similar
fixme:
Expand All @@ -10,7 +15,7 @@ plugins:
flog:
enabled: true
config:
score_threshold: 25.0
score_threshold: 28.5
exclude_patterns:
- 'spec/'
# Markdown lint with rules from https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md
Expand Down
17 changes: 14 additions & 3 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,28 @@ permissions:
contents: read

jobs:
lint:
lint-rubocop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3.0
ruby-version: 3.3.6
bundler-cache: true
- name: Run rubocop
run: bundle exec rubocop
lint-rbs-steep:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3.6
bundler-cache: true
- name: Run rbs + steep
run: bundle exec steep check
spec:
runs-on: ubuntu-latest
strategy:
Expand Down Expand Up @@ -63,7 +74,7 @@ jobs:
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3.0
ruby-version: 3.3.6
bundler-cache: true
- name: Report rspec test coverage to coveralls.io
env:
Expand Down
5 changes: 5 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1327,6 +1327,8 @@ Metrics/AbcSize:
# The ABC size is a calculated magnitude, so this number can be an Integer or
# a Float.
Max: 20
AllowedMethods:
- 'closest_node'
Exclude:
- 'tasks/*.rb'

Expand All @@ -1353,6 +1355,9 @@ Metrics/ClassLength:
# Avoid complex methods.
Metrics/CyclomaticComplexity:
Max: 6
AllowedMethods:
- 'children_match_prefix'
- 'closest_node'

Metrics/MethodLength:
CountComments: false # count full line comments?
Expand Down
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ group :development do
gem 'flamegraph'
gem 'memory_profiler'
gem 'pry'
gem 'racc'
gem 'rake'
gem 'rbs'
gem 'rspec'
gem 'ruby-prof'
gem 'stackprof'
gem 'steep'
gem 'yard'
end

Expand Down
35 changes: 35 additions & 0 deletions Steepfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

# D = Steep::Diagnostic
#
target :lib do
signature 'sig'

check 'lib'
# check 'tasks'

# check 'Gemfile'
# check 'Guardfile'
# check 'Rakefile'
# check 'Steepfile'

# library 'rubyzip'
library 'yaml'
library 'securerandom'

# configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
# configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
# configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
# configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
# configure_code_diagnostics do |hash| # You can setup everything yourself
# hash[D::Ruby::NoMethod] = :information
# end
end

# target :test do
# signature 'sig', 'sig-private'
#
# check 'test'
#
# # library 'pathname' # Standard libraries
# end
6 changes: 3 additions & 3 deletions lib/rambling/trie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def create filepath = nil, reader = nil
if filepath
reader ||= readers.resolve filepath
# noinspection RubyMismatchedArgumentType,RubyNilAnalysis
reader.each_word filepath do |word|
(reader || raise).each_word filepath do |word|
container << word
end
end
Expand All @@ -48,7 +48,7 @@ def create filepath = nil, reader = nil
# discouraged. Only use the +.marshal+ format with trusted input.
def load filepath, serializer = nil
serializer ||= serializers.resolve filepath
root = serializer.load filepath
root = (serializer || raise).load filepath
Rambling::Trie::Container.new root, compressor do |container|
yield container if block_given?
end
Expand All @@ -66,7 +66,7 @@ def load filepath, serializer = nil
def dump trie, filepath, serializer = nil
serializer ||= serializers.resolve filepath
# noinspection RubyNilAnalysis
serializer.dump trie.root, filepath
(serializer || raise).dump trie.root, filepath
end

# Provides configuration properties for the +Rambling::Trie+ gem.
Expand Down
4 changes: 3 additions & 1 deletion lib/rambling/trie/compressor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ module Trie
# Responsible for the compression process of a trie data structure.
class Compressor
# Compresses a {Nodes::Node Node} from a trie data structure.
# @param [Nodes::Raw] node the node to compress.
# @param [Nodes::Node] node the node to compress.
# @return [Nodes::Compressed] node the compressed version of the node.
def compress node
return if node.nil?

if node.compressible?
compress_child_and_merge node
else
Expand Down
12 changes: 10 additions & 2 deletions lib/rambling/trie/configuration/provider_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ def providers
# @param [String] filepath the filepath to resolve into a provider.
# @return [TProvider, nil] the provider for the given file's extension. {#default} if not found.
def resolve filepath
providers[file_format filepath] || default
extension = file_format filepath
if providers.key? extension
providers[extension]
else
default
end
end

# Resets the provider collection to the initial values.
Expand Down Expand Up @@ -104,7 +109,10 @@ def file_format filepath
end

def contains? provider
provider.nil? || (providers.any? && provider_instances.include?(provider))
return true if provider.nil?

p = provider || raise
providers.any? && provider_instances.include?(p)
end

alias_method :provider_instances, :values
Expand Down
14 changes: 8 additions & 6 deletions lib/rambling/trie/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def initialize root, compressor
# @see Nodes::Raw#add
# @see Nodes::Compressed#add
def add word
root.add char_symbols word
root.add reversed_char_symbols word
end

# Adds all provided words to the trie.
Expand Down Expand Up @@ -98,7 +98,7 @@ def scan word = ''

# Returns all words within a string that match a word contained in the trie.
# @param [String] phrase the string to look for matching words in.
# @return [Enumerator<String>] all the words in the given string that match a word in the trie.
# @return [Array<String>] all the words in the given string that match a word in the trie.
# @yield [String] each word found in phrase.
def words_within phrase
words_within_root(phrase).to_a
Expand Down Expand Up @@ -201,19 +201,21 @@ def words_within_root phrase
return enum_for :words_within_root, phrase unless block_given?

chars = phrase.chars
# rubocop:disable Style/CommentedKeyword
0.upto(chars.length - 1).each do |starting_index|
new_phrase = chars.slice starting_index..(chars.length - 1)
new_phrase = chars.slice starting_index..(chars.length - 1) # : Array[String]
root.match_prefix new_phrase do |word|
yield word
end
end
end # : Enumerator[String, void]
# rubocop:enable Style/CommentedKeyword
end

def compress_root
compressor.compress root
compressor.compress root # : Nodes::Compressed
end

def char_symbols word
def reversed_char_symbols word
symbols = []
word.reverse.each_char { |c| symbols << c.to_sym }
symbols
Expand Down
2 changes: 2 additions & 0 deletions lib/rambling/trie/enumerable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ module Trie
module Enumerable
include ::Enumerable

EMPTY_ENUMERATOR = [].to_enum :each

# Returns number of words contained in the trie
# @see https://ruby-doc.org/3.3.0/Enumerable.html#method-i-count Enumerable#count
alias_method :size, :count
Expand Down
22 changes: 11 additions & 11 deletions lib/rambling/trie/nodes/compressed.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ def compressed?
private

def partial_word_chars? chars
child = children_tree[chars.first.to_sym]
child = children_tree[(chars.first || raise).to_sym]
return false unless child

child_letter = child.letter.to_s

if chars.size >= child_letter.size
letter = chars.slice!(0, child_letter.size).join
letter = (chars.slice!(0, child_letter.size) || raise).join
return child.partial_word? chars if child_letter == letter
end

Expand All @@ -39,7 +39,7 @@ def partial_word_chars? chars
end

def word_chars? chars
letter = chars.slice! 0
letter = chars.slice!(0) || raise
letter_sym = letter.to_sym

child = children_tree[letter_sym]
Expand All @@ -50,21 +50,21 @@ def word_chars? chars

break if chars.empty?

letter << chars.slice!(0)
letter << (chars.slice!(0) || raise)
letter_sym = letter.to_sym
end

false
end

def closest_node chars
child = children_tree[chars.first.to_sym]
child = children_tree[(chars.first || raise).to_sym]
return missing unless child

child_letter = child.letter.to_s

if chars.size >= child_letter.size
letter = chars.slice!(0, child_letter.size).join
letter = (chars.slice!(0, child_letter.size) || raise).join
return child.scan chars if child_letter == letter
end

Expand All @@ -77,15 +77,15 @@ def closest_node chars
def children_match_prefix chars
return enum_for :children_match_prefix, chars unless block_given?

return if chars.empty?
return EMPTY_ENUMERATOR if chars.empty?

child = children_tree[chars.first.to_sym]
return unless child
child = children_tree[(chars.first || raise).to_sym]
return EMPTY_ENUMERATOR unless child

child_letter = child.letter.to_s
letter = chars.slice!(0, child_letter.size).join
letter = (chars.slice!(0, child_letter.size) || raise).join

return unless child_letter == letter
return EMPTY_ENUMERATOR unless child_letter == letter

child.match_prefix chars do |word|
yield word
Expand Down
25 changes: 23 additions & 2 deletions lib/rambling/trie/nodes/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class Node
# Creates a new node.
# @param [Symbol, nil] letter the Node's letter value.
# @param [Node, nil] parent the parent of the current node.
# @param [Hash<Symbol, Node>] children_tree the children tree of the current node.
def initialize letter = nil, parent = nil, children_tree = {}
@letter = letter
@parent = parent
Expand All @@ -52,6 +53,8 @@ def first_child
# rubocop:disable Lint/UnreachableLoop
children_tree.each_value { |child| return child }
# rubocop:enable Lint/UnreachableLoop

nil
end

# Indicates if the current node is the root node.
Expand Down Expand Up @@ -106,7 +109,7 @@ def scan chars
end

# Returns all words that match a prefix of any length within chars.
# @param [String] chars the chars to base the prefix on.
# @param [Array[String]] chars the chars to base the prefix on.
# @return [Enumerator<String>] all the words that match a prefix by chars.
# @yield [String] each word found.
def match_prefix chars
Expand Down Expand Up @@ -147,7 +150,7 @@ def key? letter
# Delete a given letter and its corresponding {Node Node} from
# this {Node Node}'s children tree.
# @param [Symbol] letter the letter to delete from the node's children tree.
# @return [Node] the node corresponding to the deleted letter.
# @return [Node, nil] the node corresponding to the deleted letter.
# @see https://ruby-doc.org/3.3.0/Hash.html#method-i-delete Hash#delete
def delete letter
children_tree.delete letter
Expand All @@ -164,6 +167,24 @@ def missing
private

attr_accessor :terminal

# abstract methods

def children_match_prefix chars
raise NotImplementedError
end

def partial_word_chars? chars
raise NotImplementedError
end

def word_chars? chars
raise NotImplementedError
end

def closest_node chars
raise NotImplementedError
end
end
end
end
Expand Down
Loading