smart_todo 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f43df881f5ab5894069683abbe3d09571232a896a429d0d2795d57e8102e42dc
4
- data.tar.gz: 070dc363e6e1aa44e605e1fe53126bfc613af23985cfc7cdb48a145fe93362e0
3
+ metadata.gz: 8e7fe4f3876be333b1df4dcd44d965e57a0725e65900f96a518bd6a49d608165
4
+ data.tar.gz: 02b5370dfc45cc2337d973db79a3a6bddccb8ae295d2ec529eebbb166247873b
5
5
  SHA512:
6
- metadata.gz: 69d9f4f170b854769a3141a41135c25463b2839274be7a6cea062b2d524fa5cee37e64c0a134f9de10944b9fce9e3580ed8f3b5ca4c8a8101528c3f9691a1c36
7
- data.tar.gz: c5b66f439a2176728ca2f8ef4297fceeaa6d9f08c1ba190d4a255b8e3164264262536681d34a9cab4a9837c2455e75ecdf1dd9dc6b7b8b9877e37ef026719c01
6
+ metadata.gz: b1bcacca903ebeb350b7abbb8af580de31904bae313c08aac9ffd53351ea8d13897bda85d6ede9e12971dcf5fa3f5a68b2ebb1f71bcbfddd443c34e6ee6c65fc
7
+ data.tar.gz: 970874dccc0323c3b009ec22a083c5096172390fe7c34bb698958cd9e89deb958f5be69dc26145c945a1aac7d740875656ea8a9eb0372dfecbd7ca04745a0a2a
@@ -0,0 +1,27 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ name: Ruby ${{ matrix.version }}
13
+ strategy:
14
+ matrix:
15
+ version: [2.5, 2.6, 2.7, 3.0]
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby ${{ matrix.version }}
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.version }}
23
+ bundler-cache: true
24
+ - name: Run Tests
25
+ run: |
26
+ bundle exec rake test
27
+
@@ -0,0 +1,22 @@
1
+ name: RuboCop
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-latest
8
+
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - name: Set up Ruby 3.0
12
+ uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: 3.0
15
+ bundler-cache: true
16
+ - name: Install gems
17
+ run: |
18
+ bundle config path vendor/bundle
19
+ bundle config set without 'default development test'
20
+ bundle install --jobs 4 --retry 3
21
+ - name: Run RuboCop
22
+ run: bundle exec rubocop --parallel
data/.rubocop.yml CHANGED
@@ -1,7 +1,7 @@
1
- inherit_from:
2
- - http://shopify.github.io/ruby-style-guide/rubocop.yml
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.5
5
+ TargetRubyVersion: 3.0
6
6
  Exclude:
7
7
  - vendor/**/*
data/Gemfile CHANGED
@@ -6,6 +6,6 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
7
  gemspec
8
8
 
9
- group :development do
10
- gem 'rubocop', '~> 0.71'
9
+ group :rubocop do
10
+ gem "rubocop-shopify", require: false
11
11
  end
data/Gemfile.lock CHANGED
@@ -1,36 +1,43 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- smart_todo (1.2.0)
4
+ smart_todo (1.3.0)
5
+ rexml
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- addressable (2.6.0)
10
- public_suffix (>= 2.0.2, < 4.0)
11
- ast (2.4.0)
12
- crack (0.4.3)
13
- safe_yaml (~> 1.0.0)
14
- hashdiff (0.4.0)
15
- jaro_winkler (1.5.3)
16
- minitest (5.11.3)
17
- parallel (1.17.0)
18
- parser (2.6.3.0)
19
- ast (~> 2.4.0)
20
- public_suffix (3.1.1)
10
+ addressable (2.8.0)
11
+ public_suffix (>= 2.0.2, < 5.0)
12
+ ast (2.4.2)
13
+ crack (0.4.5)
14
+ rexml
15
+ hashdiff (1.0.1)
16
+ minitest (5.14.4)
17
+ parallel (1.21.0)
18
+ parser (3.0.2.0)
19
+ ast (~> 2.4.1)
20
+ public_suffix (4.0.6)
21
21
  rainbow (3.0.0)
22
- rake (10.5.0)
23
- rubocop (0.71.0)
24
- jaro_winkler (~> 1.5.1)
22
+ rake (13.0.6)
23
+ regexp_parser (2.1.1)
24
+ rexml (3.2.5)
25
+ rubocop (1.23.0)
25
26
  parallel (~> 1.10)
26
- parser (>= 2.6)
27
+ parser (>= 3.0.0.0)
27
28
  rainbow (>= 2.2.2, < 4.0)
29
+ regexp_parser (>= 1.8, < 3.0)
30
+ rexml
31
+ rubocop-ast (>= 1.12.0, < 2.0)
28
32
  ruby-progressbar (~> 1.7)
29
- unicode-display_width (>= 1.4.0, < 1.7)
30
- ruby-progressbar (1.10.1)
31
- safe_yaml (1.0.5)
32
- unicode-display_width (1.6.0)
33
- webmock (3.6.0)
33
+ unicode-display_width (>= 1.4.0, < 3.0)
34
+ rubocop-ast (1.13.0)
35
+ parser (>= 3.0.1.1)
36
+ rubocop-shopify (2.3.0)
37
+ rubocop (~> 1.22)
38
+ ruby-progressbar (1.11.0)
39
+ unicode-display_width (2.1.0)
40
+ webmock (3.11.2)
34
41
  addressable (>= 2.3.6)
35
42
  crack (>= 0.3.2)
36
43
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -39,12 +46,12 @@ PLATFORMS
39
46
  ruby
40
47
 
41
48
  DEPENDENCIES
42
- bundler (~> 1.17)
49
+ bundler (>= 1.17)
43
50
  minitest (~> 5.0)
44
- rake (~> 10.0)
45
- rubocop (~> 0.71)
51
+ rake (>= 10.0)
52
+ rubocop-shopify
46
53
  smart_todo!
47
54
  webmock
48
55
 
49
56
  BUNDLED WITH
50
- 1.17.3
57
+ 2.2.25
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  <img src="https://user-images.githubusercontent.com/8122246/61341925-b936d180-a848-11e9-95c1-0d2f398c51b1.png?raw=true" width="200">
3
3
  </h3>
4
4
 
5
- [![Build Status](https://travis-ci.com/Shopify/smart_todo.svg?branch=master)](https://travis-ci.com/Shopify/smart_todo)
5
+ [![Build Status](https://github.com/Shopify/smart_todo/workflows/CI/badge.svg)](https://github.com/Shopify/smart_todo/actions?query=workflow%3ACI)
6
6
 
7
7
  _SmartTodo_ is a library designed to assign users on TODO comments written in your codebase and help assignees be reminded when it's time to commit to their TODO.
8
8
 
data/dev.yml CHANGED
@@ -4,7 +4,7 @@ type:
4
4
  - ruby
5
5
 
6
6
  up:
7
- - ruby: 2.5.5
7
+ - ruby: 2.7.4
8
8
  - bundler
9
9
 
10
10
  test:
data/exe/smart_todo CHANGED
@@ -3,10 +3,10 @@
3
3
 
4
4
  $LOAD_PATH.unshift("#{__dir__}/../lib")
5
5
 
6
- require 'smart_todo'
6
+ require "smart_todo"
7
7
 
8
- if ENV['ENABLE_SMART_TODO'] && !ARGV.include?('--dispatcher')
9
- ARGV << '--dispatcher' << 'slack'
8
+ if ENV["ENABLE_SMART_TODO"] && !ARGV.include?("--dispatcher")
9
+ ARGV << "--dispatcher" << "slack"
10
10
  end
11
11
 
12
12
  SmartTodo::CLI.new.run
@@ -15,13 +15,13 @@ module SmartTodo
15
15
  def run(args = ARGV)
16
16
  paths = define_options.parse!(args)
17
17
  validate_options!
18
- paths << '.' if paths.empty?
18
+ paths << "." if paths.empty?
19
19
 
20
20
  paths.each do |path|
21
21
  normalize_path(path).each do |file|
22
22
  parse_file(file)
23
23
 
24
- STDOUT.print('.')
24
+ STDOUT.print(".")
25
25
  STDOUT.flush
26
26
  end
27
27
  end
@@ -38,13 +38,13 @@ module SmartTodo
38
38
  def define_options
39
39
  OptionParser.new do |opts|
40
40
  opts.banner = "Usage: smart_todo [options] file_or_path1 file_or_path2 ..."
41
- opts.on('--slack_token TOKEN') do |token|
41
+ opts.on("--slack_token TOKEN") do |token|
42
42
  @options[:slack_token] = token
43
43
  end
44
- opts.on('--fallback_channel CHANNEL') do |channel|
44
+ opts.on("--fallback_channel CHANNEL") do |channel|
45
45
  @options[:fallback_channel] = channel
46
46
  end
47
- opts.on('--dispatcher DISPATCHER') do |dispatcher|
47
+ opts.on("--dispatcher DISPATCHER") do |dispatcher|
48
48
  @options[:dispatcher] = dispatcher
49
49
  end
50
50
  end
@@ -67,7 +67,7 @@ module SmartTodo
67
67
 
68
68
  # @param file [String] a path to a file
69
69
  def parse_file(file)
70
- Parser::CommentParser.new(File.read(file, encoding: 'UTF-8')).parse.each do |todo_node|
70
+ Parser::CommentParser.new(File.read(file, encoding: "UTF-8")).parse.each do |todo_node|
71
71
  event_message = nil
72
72
  event_met = todo_node.metadata.events.find do |event|
73
73
  event_message = Events.public_send(event.method_name, *event.arguments)
@@ -12,7 +12,7 @@ module SmartTodo
12
12
  case dispatcher
13
13
  when "slack"
14
14
  Slack
15
- when nil, 'output'
15
+ when nil, "output"
16
16
  Output
17
17
  end
18
18
  end
@@ -25,7 +25,7 @@ module SmartTodo
25
25
  #
26
26
  # @return void
27
27
  def self.validate_options!(_options)
28
- raise(NotImplemetedError, 'subclass responsability')
28
+ raise(NotImplemetedError, "subclass responsability")
29
29
  end
30
30
 
31
31
  # @param event_message [String] the success message associated
@@ -38,7 +38,7 @@ module SmartTodo
38
38
  @todo_node = todo_node
39
39
  @options = options
40
40
  @file = file
41
- @assignee = @todo_node.metadata.assignee
41
+ @assignees = @todo_node.metadata.assignees
42
42
  end
43
43
 
44
44
  # This method gets called when a TODO reminder is expired and needs to be delivered.
@@ -46,7 +46,7 @@ module SmartTodo
46
46
  #
47
47
  # @return void
48
48
  def dispatch
49
- raise(NotImplemetedError, 'subclass responsability')
49
+ raise(NotImplemetedError, "subclass responsability")
50
50
  end
51
51
 
52
52
  private
@@ -54,10 +54,11 @@ module SmartTodo
54
54
  # Prepare the content of the message to send to the TODO assignee
55
55
  #
56
56
  # @param user [Hash] contain information about a user
57
+ # @param assignee [String] original string handle the slack message should be sent
57
58
  # @return [String]
58
- def slack_message(user)
59
- header = if user.key?('fallback')
60
- unexisting_user
59
+ def slack_message(user, assignee)
60
+ header = if user.key?("fallback")
61
+ unexisting_user(assignee)
61
62
  else
62
63
  existing_user
63
64
  end
@@ -78,12 +79,13 @@ module SmartTodo
78
79
 
79
80
  # Message in case a TODO's assignee doesn't exist in the Slack organization
80
81
  #
82
+ # @param user [Hash]
81
83
  # @return [String]
82
- def unexisting_user
83
- "Hello :wave:,\n\n`#{@assignee}` had an assigned TODO but this user or channel doesn't exist on Slack anymore."
84
+ def unexisting_user(assignee)
85
+ "Hello :wave:,\n\n`#{assignee}` had an assigned TODO but this user or channel doesn't exist on Slack anymore."
84
86
  end
85
87
 
86
- # @param user [Hash]
88
+ # Hello message for user actually existing in the organization
87
89
  def existing_user
88
90
  "Hello :wave:,"
89
91
  end
@@ -6,9 +6,21 @@ module SmartTodo
6
6
  # (using the associated slack email address) or a channel.
7
7
  class Slack < Base
8
8
  def self.validate_options!(options)
9
- options[:slack_token] ||= ENV.fetch('SMART_TODO_SLACK_TOKEN') { raise(ArgumentError, 'Missing :slack_token') }
9
+ options[:slack_token] ||= ENV.fetch("SMART_TODO_SLACK_TOKEN") { raise(ArgumentError, "Missing :slack_token") }
10
10
 
11
- options.fetch(:fallback_channel) { raise(ArgumentError, 'Missing :fallback_channel') }
11
+ options.fetch(:fallback_channel) { raise(ArgumentError, "Missing :fallback_channel") }
12
+ end
13
+
14
+ # Make a Slack API call to dispatch the message to each assignee
15
+ #
16
+ # @raise [SlackClient::Error] in case the Slack API returns an error
17
+ # other than `users_not_found`
18
+ #
19
+ # @return [Array] Slack response for each assignee a message was sent to
20
+ def dispatch
21
+ @assignees.each do |assignee|
22
+ dispatch_one(assignee)
23
+ end
12
24
  end
13
25
 
14
26
  # Make a Slack API call to dispatch the message to the user or channel
@@ -16,19 +28,20 @@ module SmartTodo
16
28
  # @raise [SlackClient::Error] in case the Slack API returns an error
17
29
  # other than `users_not_found`
18
30
  #
31
+ # @param [String] the assignee handle string
19
32
  # @return [Hash] the Slack response
20
- def dispatch
21
- user = slack_user_or_channel
33
+ def dispatch_one(assignee)
34
+ user = slack_user_or_channel(assignee)
22
35
 
23
- client.post_message(user.dig('user', 'id'), slack_message(user))
36
+ client.post_message(user.dig("user", "id"), slack_message(user, assignee))
24
37
  rescue SlackClient::Error => error
25
- if %w(users_not_found channel_not_found).include?(error.error_code)
26
- user = { 'user' => { 'id' => @options[:fallback_channel] }, 'fallback' => true }
38
+ if ["users_not_found", "channel_not_found"].include?(error.error_code)
39
+ user = { "user" => { "id" => @options[:fallback_channel] }, "fallback" => true }
27
40
  else
28
41
  raise(error)
29
42
  end
30
43
 
31
- client.post_message(user.dig('user', 'id'), slack_message(user))
44
+ client.post_message(user.dig("user", "id"), slack_message(user, assignee))
32
45
  end
33
46
 
34
47
  private
@@ -37,11 +50,11 @@ module SmartTodo
37
50
  # the channel the message should be sent to.
38
51
  #
39
52
  # @return [Hash] a suited hash containing the user ID for a given individual or a slack channel
40
- def slack_user_or_channel
41
- if email?
42
- client.lookup_user_by_email(@assignee)
53
+ def slack_user_or_channel(assignee)
54
+ if assignee.include?("@")
55
+ client.lookup_user_by_email(assignee)
43
56
  else
44
- { 'user' => { 'id' => @assignee } }
57
+ { "user" => { "id" => assignee } }
45
58
  end
46
59
  end
47
60
 
@@ -49,13 +62,6 @@ module SmartTodo
49
62
  def client
50
63
  @client ||= SlackClient.new(@options[:slack_token])
51
64
  end
52
-
53
- # Check if the TODO's assignee is a specific user or a channel
54
- #
55
- # @return [true, false]
56
- def email?
57
- @assignee.include?("@")
58
- end
59
65
  end
60
66
  end
61
67
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'time'
3
+ require "time"
4
4
 
5
5
  module SmartTodo
6
6
  module Events
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- gem('bundler')
4
- require 'bundler'
3
+ gem("bundler")
4
+ require "bundler"
5
5
 
6
6
  module SmartTodo
7
7
  module Events
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
- require 'json'
3
+ require "net/http"
4
+ require "json"
5
5
 
6
6
  module SmartTodo
7
7
  module Events
@@ -30,7 +30,7 @@ module SmartTodo
30
30
  if response.code_type < Net::HTTPClientError
31
31
  error_message
32
32
  elsif (gem = version_released?(response.body))
33
- message(gem['number'])
33
+ message(gem["number"])
34
34
  else
35
35
  false
36
36
  end
@@ -54,13 +54,13 @@ module SmartTodo
54
54
  # @return [true, false]
55
55
  def version_released?(gem_versions)
56
56
  JSON.parse(gem_versions).find do |gem|
57
- @requirements.satisfied_by?(Gem::Version.new(gem['number']))
57
+ @requirements.satisfied_by?(Gem::Version.new(gem["number"]))
58
58
  end
59
59
  end
60
60
 
61
61
  # @return [Net::HTTP] an instance of Net::HTTP
62
62
  def client
63
- @client ||= Net::HTTP.new('rubygems.org', Net::HTTP.https_default_port).tap do |client|
63
+ @client ||= Net::HTTP.new("rubygems.org", Net::HTTP.https_default_port).tap do |client|
64
64
  client.use_ssl = true
65
65
  end
66
66
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
- require 'json'
3
+ require "net/http"
4
+ require "json"
5
5
 
6
6
  module SmartTodo
7
7
  module Events
@@ -12,7 +12,7 @@ module SmartTodo
12
12
  # with the `repos` scope in the +SMART_TODO_GITHUB_TOKEN+ environment variable
13
13
  # is required.
14
14
  class IssueClose
15
- TOKEN_ENV = 'SMART_TODO_GITHUB_TOKEN'
15
+ TOKEN_ENV = "SMART_TODO_GITHUB_TOKEN"
16
16
 
17
17
  # @param organization [String]
18
18
  # @param repo [String]
@@ -62,7 +62,7 @@ module SmartTodo
62
62
 
63
63
  # @return [Net::HTTP] an instance of Net::HTTP
64
64
  def client
65
- @client ||= Net::HTTP.new('api.github.com', Net::HTTP.https_default_port).tap do |client|
65
+ @client ||= Net::HTTP.new("api.github.com", Net::HTTP.https_default_port).tap do |client|
66
66
  client.use_ssl = true
67
67
  end
68
68
  end
@@ -72,13 +72,13 @@ module SmartTodo
72
72
  #
73
73
  # @return [true, false]
74
74
  def pull_request_closed?(pull_request)
75
- JSON.parse(pull_request)['state'] == 'closed'
75
+ JSON.parse(pull_request)["state"] == "closed"
76
76
  end
77
77
 
78
78
  # @return [Hash]
79
79
  def default_headers
80
- { 'Accept' => 'application/vnd.github.v3+json' }.tap do |headers|
81
- headers['Authorization'] = "token #{ENV[TOKEN_ENV]}" if ENV[TOKEN_ENV]
80
+ { "Accept" => "application/vnd.github.v3+json" }.tap do |headers|
81
+ headers["Authorization"] = "token #{ENV[TOKEN_ENV]}" if ENV[TOKEN_ENV]
82
82
  end
83
83
  end
84
84
  end
@@ -54,7 +54,7 @@ module SmartTodo
54
54
  # @param issue_number [String, Integer]
55
55
  # @return [false, String]
56
56
  def issue_close(organization, repo, issue_number)
57
- IssueClose.new(organization, repo, issue_number, type: 'issues').met?
57
+ IssueClose.new(organization, repo, issue_number, type: "issues").met?
58
58
  end
59
59
 
60
60
  # Check if the pull request +pr_number+ is closed
@@ -64,7 +64,7 @@ module SmartTodo
64
64
  # @param pr_number [String, Integer]
65
65
  # @return [false, String]
66
66
  def pull_request_close(organization, repo, pr_number)
67
- IssueClose.new(organization, repo, pr_number, type: 'pulls').met?
67
+ IssueClose.new(organization, repo, pr_number, type: "pulls").met?
68
68
  end
69
69
  end
70
70
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper'
3
+ require "ripper"
4
4
 
5
5
  module SmartTodo
6
6
  module Parser
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ripper'
3
+ require "ripper"
4
4
 
5
5
  module SmartTodo
6
6
  module Parser
@@ -35,7 +35,7 @@ module SmartTodo
35
35
  # @param args [Array]
36
36
  # @return [Array, MethodNode]
37
37
  def on_method_add_arg(method, args)
38
- if method == 'TODO'
38
+ if method == "TODO"
39
39
  args
40
40
  else
41
41
  MethodNode.new(method, args)
@@ -58,12 +58,12 @@ module SmartTodo
58
58
  # @param key [String]
59
59
  # @param value [String, Integer, MethodNode]
60
60
  def on_assoc_new(key, value)
61
- key.tr!(':', '')
61
+ key.tr!(":", "")
62
62
 
63
63
  case key
64
- when 'on'
64
+ when "on"
65
65
  [:on_todo_event, value]
66
- when 'to'
66
+ when "to"
67
67
  [:on_todo_assignee, value]
68
68
  else
69
69
  [:unknown, value]
@@ -78,10 +78,11 @@ module SmartTodo
78
78
  end
79
79
 
80
80
  class Visitor
81
- attr_reader :events, :assignee
81
+ attr_reader :events, :assignees
82
82
 
83
83
  def initialize
84
84
  @events = []
85
+ @assignees = []
85
86
  end
86
87
 
87
88
  # Iterate over each tokens returned from the parser and call
@@ -111,7 +112,7 @@ module SmartTodo
111
112
  # @param assignee [String]
112
113
  # @return [void]
113
114
  def on_todo_assignee(assignee)
114
- @assignee = assignee
115
+ @assignees << assignee
115
116
  end
116
117
  end
117
118
  end
@@ -11,7 +11,7 @@ module SmartTodo
11
11
 
12
12
  # @param todo [String] the actual Ruby comment
13
13
  def initialize(todo)
14
- @metadata = MetadataParser.parse(todo.gsub(/^#/, ''))
14
+ @metadata = MetadataParser.parse(todo.gsub(/^#/, ""))
15
15
  @comments = []
16
16
  @start = todo.match(/^#(\s+)/)[1].size
17
17
  end
@@ -26,7 +26,7 @@ module SmartTodo
26
26
  # @param comment [String]
27
27
  # @return [void]
28
28
  def <<(comment)
29
- @comments << comment.gsub(/^#(\s+)/, '')
29
+ @comments << comment.gsub(/^#(\s+)/, "")
30
30
  end
31
31
 
32
32
  # Check if the +comment+ is indented two spaces below the
@@ -36,7 +36,7 @@ module SmartTodo
36
36
  # @param comment [String]
37
37
  # @return [true, false]
38
38
  def indented_comment?(comment)
39
- comment.match(/^#(\s+)/)[1].size - @start == DEFAULT_RUBY_INDENTATION
39
+ comment.match(/^#(\s*)/)[1].size - @start == DEFAULT_RUBY_INDENTATION
40
40
  end
41
41
  end
42
42
  end