danger-todoist 1.2.3 → 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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +3 -4
- data/CHANGELOG.md +5 -0
- data/Dangerfile +10 -4
- data/README.md +3 -0
- data/danger-todoist.gemspec +3 -4
- data/lib/danger_plugin.rb +1 -0
- data/lib/todoist/diff_inline_todo_finder.rb +22 -0
- data/lib/todoist/diff_todo_finder.rb +88 -23
- data/lib/todoist/gem_version.rb +1 -1
- data/lib/todoist/plugin.rb +10 -4
- data/lib/todoist/todo.rb +1 -1
- data/spec/diff_inline_todo_finder_spec.rb +35 -0
- data/spec/diff_todo_finder_spec.rb +21 -13
- data/spec/fixtures/multiline_todo_patch.diff +14 -0
- data/spec/fixtures/sample_patch.diff +36 -0
- data/spec/matches_in_diff_spec.rb +76 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/todoist_spec.rb +5 -3
- metadata +26 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87a34fb9d9b0148fefa1215d0c4d3fa41349e4db
|
4
|
+
data.tar.gz: a53a69753b59d4b53eada001d6bfbdc7ff44e408
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe90da46ae4654bd4d335eac952381ceebfed5bb6b415e42b3c82702f05987b385edfd0d57db0d3827f8b38f7840f95aa812286b983a61df0d370a32db7030cb
|
7
|
+
data.tar.gz: 104a01bddd67932185013df9d8d379298c2abf6e29fde20f854385bedba0f0709a1b2a496dc757dc6b528ee8993e1c4277d33b894d38967617d9a27bef1e88cd
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -4,3 +4,18 @@ Style/StringLiterals:
|
|
4
4
|
|
5
5
|
Style/StructInheritance:
|
6
6
|
Enabled: false
|
7
|
+
|
8
|
+
PercentLiteralDelimiters:
|
9
|
+
PreferredDelimiters:
|
10
|
+
"%": ()
|
11
|
+
"%i": ()
|
12
|
+
"%q": ()
|
13
|
+
"%Q": ()
|
14
|
+
"%r": "{}"
|
15
|
+
"%s": ()
|
16
|
+
"%w": ()
|
17
|
+
"%W": ()
|
18
|
+
"%x": ()
|
19
|
+
|
20
|
+
Layout/IndentHeredoc:
|
21
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Dangerfile
CHANGED
@@ -1,11 +1,17 @@
|
|
1
|
+
is_wip = github.pr_title.include? "[WIP]"
|
2
|
+
is_trivial = github.pr_title.include? "[trivial]"
|
3
|
+
is_big_pr = git.lines_of_code > 500
|
4
|
+
has_insufficient_description = github.pr_body.length < 5
|
5
|
+
has_updated_changelog = git.modified_files.include?("CHANGELOG.md")
|
6
|
+
|
1
7
|
# Make it more obvious that a PR is a work in progress and shouldn't be merged yet
|
2
|
-
warn("PR is classed as Work in Progress") if
|
8
|
+
warn("PR is classed as Work in Progress") if is_wip
|
3
9
|
|
4
10
|
# Warn when there is a big PR
|
5
|
-
warn("
|
11
|
+
warn("Wow that's a lot of changes. Can we split this up?") if is_big_pr
|
6
12
|
|
7
13
|
# Reminder to add changelog entry
|
8
|
-
|
14
|
+
if !has_updated_changelog && !is_trivial
|
9
15
|
fail("Please include a CHANGELOG entry.", sticky: false)
|
10
16
|
end
|
11
17
|
|
@@ -16,6 +22,6 @@ todoist.print_todos_table
|
|
16
22
|
|
17
23
|
# Mainly to encourage writing up some reasoning about the PR, rather than
|
18
24
|
# just leaving a title
|
19
|
-
if
|
25
|
+
if has_insufficient_description
|
20
26
|
fail "Please provide a summary in the Pull Request description"
|
21
27
|
end
|
data/README.md
CHANGED
@@ -65,4 +65,7 @@ todoist.todos.each { |todo| puts todo.text }</pre>
|
|
65
65
|
4. Use `bundle exec guard` to automatically have tests run as you make changes.
|
66
66
|
5. Make your changes.
|
67
67
|
|
68
|
+
## Licence
|
68
69
|
|
70
|
+
This project is MIT licenced. Parts of the code (see class `Patch`) are heavily
|
71
|
+
inspired by [ruby-git_diff_parser](https://github.com/packsaddle/ruby-git_diff_parser).
|
data/danger-todoist.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require "todoist/gem_version.rb"
|
@@ -26,13 +25,13 @@ Gem::Specification.new do |spec|
|
|
26
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
26
|
|
28
27
|
# Testing support
|
28
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0"
|
29
29
|
spec.add_development_dependency "rspec", "~> 3.4"
|
30
30
|
spec.add_development_dependency "simplecov", "~> 0.12"
|
31
|
-
spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0"
|
32
31
|
|
33
32
|
# Linting code and docs
|
34
|
-
spec.add_development_dependency "rubocop", "
|
35
|
-
spec.add_development_dependency "yard", "~> 0.
|
33
|
+
spec.add_development_dependency "rubocop", "0.50"
|
34
|
+
spec.add_development_dependency "yard", "~> 0.9.12"
|
36
35
|
|
37
36
|
# Makes testing easy via `bundle exec guard`
|
38
37
|
spec.add_development_dependency "guard", "~> 2.14"
|
data/lib/danger_plugin.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Danger
|
2
|
+
# Identify inline todos in a set of diffs
|
3
|
+
class DiffInlineTodoFinder
|
4
|
+
def initialize(keywords)
|
5
|
+
@keywords = keywords
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(diffs)
|
9
|
+
diffs.map do |diff|
|
10
|
+
diff.patch.scan(/\+ .{3,}(#{keywords})[\s:]{1}(.+)$/).map do |match|
|
11
|
+
Todo.new(diff.path, match[1].strip)
|
12
|
+
end
|
13
|
+
end.flatten
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def keywords
|
19
|
+
@keywords.join("|")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -2,45 +2,110 @@ module Danger
|
|
2
2
|
# Identify todos in a set of diffs
|
3
3
|
class DiffTodoFinder
|
4
4
|
def initialize(keywords)
|
5
|
-
@
|
5
|
+
@regexp = todo_regexp(keywords)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
matches.each do |match|
|
16
|
-
todos << Danger::Todo.new(diff.path, clean_todo_text(match))
|
17
|
-
end
|
18
|
-
end
|
19
|
-
todos
|
8
|
+
def call(diffs)
|
9
|
+
diffs
|
10
|
+
.map { |diff| MatchesInDiff.new(diff, diff.patch.scan(@regexp)) }
|
11
|
+
.select(&:todo_matches?)
|
12
|
+
.map(&:all_todos)
|
13
|
+
.flatten
|
20
14
|
end
|
21
15
|
|
22
16
|
private
|
23
17
|
|
24
|
-
def clean_todo_text(match)
|
25
|
-
comment_indicator, _, entire_todo = match
|
26
|
-
entire_todo.gsub(comment_indicator, "")
|
27
|
-
.delete("\n")
|
28
|
-
.strip
|
29
|
-
end
|
30
|
-
|
31
18
|
# this is quite a mess now ... I knew it would haunt me.
|
32
19
|
# to aid debugging, this online regexr can be
|
33
20
|
# used: http://rubular.com/r/DPkoE2ztpn
|
34
21
|
# the regexp uses backreferences to match the comment indicator multiple
|
35
22
|
# times if possible
|
36
|
-
def todo_regexp
|
23
|
+
def todo_regexp(keywords)
|
37
24
|
/
|
38
25
|
(?<comment_indicator>^\+\s*[^a-z0-9\+\s]+)
|
39
26
|
(\n\+)?\s+
|
40
|
-
(?<todo_indicator>#{
|
27
|
+
(?<todo_indicator>#{keywords.join("|")})[\s:]{1}
|
41
28
|
(?<entire_text>(?<text>[^\n]*)
|
42
|
-
(?<rest>\n\k<comment_indicator>\s*[\w .]*)*)
|
29
|
+
(?<rest>\n\k<comment_indicator>\s*[\w .']*)*)
|
43
30
|
/ixm
|
44
31
|
end
|
45
32
|
end
|
33
|
+
|
34
|
+
# Identify todos in a single diff
|
35
|
+
class MatchesInDiff < Struct.new(:diff, :matches)
|
36
|
+
def todo_matches?
|
37
|
+
!matches.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
def all_todos
|
41
|
+
matches.map { |match| build_todo(diff.path, match) }
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def line_number(match)
|
47
|
+
_, _, _, first_text = match
|
48
|
+
Patch.new(diff.patch).changed_lines.each do |line|
|
49
|
+
return line.number if line.content.include? first_text
|
50
|
+
end
|
51
|
+
raise TextNotFoundInPatchError
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_todo(path, match)
|
55
|
+
Danger::Todo.new(path, cleaned_todo_text(match), line_number(match))
|
56
|
+
end
|
57
|
+
|
58
|
+
def cleaned_todo_text(match)
|
59
|
+
comment_indicator, _, entire_todo = match
|
60
|
+
entire_todo.gsub(comment_indicator, "")
|
61
|
+
.delete("\n")
|
62
|
+
.strip
|
63
|
+
end
|
64
|
+
|
65
|
+
# Parsed patch
|
66
|
+
class Patch
|
67
|
+
RANGE_INFORMATION_LINE = /^@@ .+\+(?<line_number>\d+),/
|
68
|
+
MODIFIED_LINE = /^\+(?!\+|\+)/
|
69
|
+
REMOVED_LINE = /^[-]/
|
70
|
+
NOT_REMOVED_LINE = /^[^-]/
|
71
|
+
|
72
|
+
def initialize(body)
|
73
|
+
@body = body
|
74
|
+
end
|
75
|
+
|
76
|
+
# rubocop:disable Metrics/MethodLength
|
77
|
+
def changed_lines
|
78
|
+
line_number = 0
|
79
|
+
|
80
|
+
lines_with_index
|
81
|
+
.each_with_object([]) do |(content, patch_position), lines|
|
82
|
+
case content
|
83
|
+
when RANGE_INFORMATION_LINE
|
84
|
+
line_number = Regexp.last_match[:line_number].to_i
|
85
|
+
when MODIFIED_LINE
|
86
|
+
lines << Line.new(content, line_number, patch_position)
|
87
|
+
line_number += 1
|
88
|
+
when NOT_REMOVED_LINE
|
89
|
+
line_number += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
# rubocop:enable Metrics/MethodLength
|
94
|
+
|
95
|
+
def lines
|
96
|
+
@body.lines
|
97
|
+
end
|
98
|
+
|
99
|
+
def lines_with_index
|
100
|
+
lines.each_with_index
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Parsed line
|
105
|
+
class Line < Struct.new(:content, :number, :patch_position)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class TextNotFoundInPatchError < RuntimeError
|
110
|
+
end
|
46
111
|
end
|
data/lib/todoist/gem_version.rb
CHANGED
data/lib/todoist/plugin.rb
CHANGED
@@ -96,7 +96,7 @@ module Danger
|
|
96
96
|
markdown("- #{file}")
|
97
97
|
todos
|
98
98
|
.select(&:text)
|
99
|
-
.each { |todo| markdown(" - #{todo.text}") }
|
99
|
+
.each { |todo| markdown(" - Line #{todo.line_number}: #{todo.text}") }
|
100
100
|
end
|
101
101
|
|
102
102
|
def call_method_for_todos(method)
|
@@ -108,8 +108,10 @@ module Danger
|
|
108
108
|
@todos = []
|
109
109
|
return if files_of_interest.empty?
|
110
110
|
|
111
|
-
@todos =
|
112
|
-
|
111
|
+
@todos = finders
|
112
|
+
.map { |finder_class| finder_class.new(keywords) }
|
113
|
+
.map { |finder| finder.call(diffs_of_interest) }
|
114
|
+
.flatten
|
113
115
|
end
|
114
116
|
|
115
117
|
def keywords
|
@@ -132,7 +134,7 @@ module Danger
|
|
132
134
|
diff = EmptyDiff.new
|
133
135
|
begin
|
134
136
|
diff = git.diff_for_file(file)
|
135
|
-
rescue
|
137
|
+
rescue NoMethodError
|
136
138
|
log_unable_to_find_diff(file.inspect)
|
137
139
|
end
|
138
140
|
diff
|
@@ -142,6 +144,10 @@ module Danger
|
|
142
144
|
def log_unable_to_find_diff(file)
|
143
145
|
markdown("* danger-todoist was unable to determine diff for \"#{file}\".")
|
144
146
|
end
|
147
|
+
|
148
|
+
def finders
|
149
|
+
[DiffTodoFinder]
|
150
|
+
end
|
145
151
|
end
|
146
152
|
|
147
153
|
# Null object incase a diff cannot be determined
|
data/lib/todoist/todo.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
module Danger
|
4
|
+
describe Danger::DiffInlineTodoFinder do
|
5
|
+
let(:subject) { Danger::DiffInlineTodoFinder.new(%w(TODO FIXME)) }
|
6
|
+
|
7
|
+
describe "#call" do
|
8
|
+
it "finds todos inline after code" do
|
9
|
+
patch = <<PATCH
|
10
|
+
+ function bla() {}; // TODO: fix this
|
11
|
+
PATCH
|
12
|
+
|
13
|
+
diff = sample_diff(patch)
|
14
|
+
|
15
|
+
todos = subject.call([diff])
|
16
|
+
|
17
|
+
expect(todos.first.text).to eq("fix this")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "doesn't find floating todos" do
|
21
|
+
patch = <<PATCH
|
22
|
+
+ # TODO: practice you must
|
23
|
+
+ def practice
|
24
|
+
+ return false
|
25
|
+
+ end
|
26
|
+
+ # FIXME: with you the force is
|
27
|
+
PATCH
|
28
|
+
|
29
|
+
todos = subject.call([sample_diff(patch)])
|
30
|
+
|
31
|
+
expect(todos).to be_empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -8,12 +8,12 @@ module Danger
|
|
8
8
|
Danger::DiffTodoFinder.new(%w(TODO FIXME))
|
9
9
|
end
|
10
10
|
|
11
|
-
describe "#
|
11
|
+
describe "#call" do
|
12
12
|
%w(TODO TODO: todo todo: FIXME fixme FIXME: fixme).each do |marker|
|
13
13
|
it "identifies a new '#{marker}' as a todo" do
|
14
14
|
diff = sample_diff("+ # #{marker} some todo")
|
15
15
|
|
16
|
-
todos = subject.
|
16
|
+
todos = subject.call([diff])
|
17
17
|
|
18
18
|
expect(todos).to_not be_empty
|
19
19
|
end
|
@@ -23,16 +23,17 @@ module Danger
|
|
23
23
|
diff = sample_diff("+ # BUG some todo")
|
24
24
|
|
25
25
|
subject = described_class.new(["BUG"])
|
26
|
-
todos = subject.
|
26
|
+
todos = subject.call([diff])
|
27
27
|
|
28
28
|
expect(todos).to_not be_empty
|
29
|
+
expect(todos.first.line_number).to be 0
|
29
30
|
end
|
30
31
|
|
31
32
|
it "doesnt crash but also doesnt find anything with empty keywords" do
|
32
33
|
diff = sample_diff("+ # BUG some todo")
|
33
34
|
|
34
35
|
subject = described_class.new([])
|
35
|
-
todos = subject.
|
36
|
+
todos = subject.call([diff])
|
36
37
|
|
37
38
|
expect(todos).to be_empty
|
38
39
|
end
|
@@ -42,7 +43,7 @@ module Danger
|
|
42
43
|
it "identifies todos in languages with '#{comment}' as comments" do
|
43
44
|
diff = sample_diff("+ #{comment} TODO: some todo")
|
44
45
|
|
45
|
-
todos = subject.
|
46
|
+
todos = subject.call([diff])
|
46
47
|
|
47
48
|
expect(todos).to_not be_empty
|
48
49
|
end
|
@@ -51,7 +52,7 @@ module Danger
|
|
51
52
|
it "does not identify removed todos as a todo" do
|
52
53
|
diff = sample_diff("- TODO: some todo")
|
53
54
|
|
54
|
-
todos = subject.
|
55
|
+
todos = subject.call([diff])
|
55
56
|
|
56
57
|
expect(todos).to be_empty
|
57
58
|
end
|
@@ -63,7 +64,7 @@ module Danger
|
|
63
64
|
"+ def todo foo",
|
64
65
|
"+ * this looks like a todo but isnt",
|
65
66
|
"+ TODO_REGEXP = /",
|
66
|
-
"+ todos = subject.
|
67
|
+
"+ todos = subject.call(diffs)",
|
67
68
|
"++ # FIXME: with you the force is",
|
68
69
|
"+ TODO: foo",
|
69
70
|
"+ TODO",
|
@@ -72,7 +73,7 @@ module Danger
|
|
72
73
|
it "does not identify occurences in '#{patch}'" do
|
73
74
|
diff = sample_diff("some/file.rb")
|
74
75
|
|
75
|
-
todos = subject.
|
76
|
+
todos = subject.call([diff])
|
76
77
|
|
77
78
|
expect(todos).to be_empty
|
78
79
|
end
|
@@ -81,7 +82,7 @@ module Danger
|
|
81
82
|
it "identifies the todo text as well" do
|
82
83
|
diff = sample_diff("+ # TODO: practice you must")
|
83
84
|
|
84
|
-
todos = subject.
|
85
|
+
todos = subject.call([diff])
|
85
86
|
|
86
87
|
expect(todos.first.text).to eql("practice you must")
|
87
88
|
end
|
@@ -95,7 +96,7 @@ module Danger
|
|
95
96
|
+ # FIXME: with you the force is
|
96
97
|
PATCH
|
97
98
|
|
98
|
-
todos = subject.
|
99
|
+
todos = subject.call([sample_diff(patch)])
|
99
100
|
|
100
101
|
expect(todos.map(&:text))
|
101
102
|
.to eql(["practice you must", "with you the force is"])
|
@@ -112,7 +113,7 @@ PATCH
|
|
112
113
|
+ */
|
113
114
|
PATCH
|
114
115
|
|
115
|
-
todos = subject.
|
116
|
+
todos = subject.call([sample_diff(patch)])
|
116
117
|
|
117
118
|
expect(todos.map(&:text)).to eql(%w(something another))
|
118
119
|
end
|
@@ -126,14 +127,21 @@ PATCH
|
|
126
127
|
+ # TODO: this is a
|
127
128
|
+ # multiline comment as well
|
128
129
|
+ function bla() {};
|
130
|
+
+ # TODO: I'd rather not have this here ...
|
131
|
+
+ # because it's probably just a bit of code that we can reimplement
|
132
|
+
+ # or steal
|
129
133
|
PATCH
|
130
134
|
|
131
|
-
todos = subject.
|
135
|
+
todos = subject.call([sample_diff(patch)])
|
132
136
|
|
133
137
|
expect(todos.map(&:text))
|
134
138
|
.to eql(["this should be parsed as a single item.",
|
135
|
-
"this is a multiline comment as well"
|
139
|
+
"this is a multiline comment as well",
|
140
|
+
"I'd rather not have this here ... because it's probably "\
|
141
|
+
"just a bit of code that we can reimplement or steal"])
|
136
142
|
end
|
137
143
|
end
|
138
144
|
end
|
145
|
+
# rubocop:enable Metrics/BlockLength
|
139
146
|
end
|
147
|
+
# rubocop:enable Metrics/ModuleLength
|
@@ -0,0 +1,14 @@
|
|
1
|
+
diff --git a/danger-todoist.gemspec b/danger-todoist.gemspec
|
2
|
+
index f5b474f..4c75b45 100644
|
3
|
+
--- a/danger-todoist.gemspec
|
4
|
+
+++ b/danger-todoist.gemspec
|
5
|
+
@@ -19,6 +19,9 @@ Gem::Specification.new do |spec|
|
6
|
+
spec.required_ruby_version = ">= 2.0.0"
|
7
|
+
|
8
|
+
spec.add_runtime_dependency "danger-plugin-api", "~> 1.0"
|
9
|
+
+ # TODO: I'd rather not have this here ...
|
10
|
+
+ # because it's probably just a bit of code that we can reimplement
|
11
|
+
+ # or steal
|
12
|
+
spec.add_runtime_dependency "git_diff_parser", "~> 3.1.0"
|
13
|
+
|
14
|
+
# General ruby development
|
@@ -0,0 +1,36 @@
|
|
1
|
+
diff --git a/lib/todoist/diff_todo_finder.rb b/lib/todoist/diff_todo_finder.rb
|
2
|
+
index b58809b..1ecc4f0 100644
|
3
|
+
--- a/lib/todoist/diff_todo_finder.rb
|
4
|
+
+++ b/lib/todoist/diff_todo_finder.rb
|
5
|
+
@@ -9,7 +9,6 @@ def initialize(keywords)
|
6
|
+
|
7
|
+
def call(diffs)
|
8
|
+
diffs
|
9
|
+
- .each { |diff| debug(diff) }
|
10
|
+
.map { |diff| MatchesInDiff.new(diff, diff.patch.scan(@regexp)) }
|
11
|
+
.select(&:todo_matches?)
|
12
|
+
.map(&:all_todos)
|
13
|
+
@@ -18,12 +17,6 @@ def call(diffs)
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
- def debug(diff)
|
18
|
+
- # GitDiffParser::Patches.new(diff.patch).each do |p|
|
19
|
+
- # puts p.changed_lines.inspect
|
20
|
+
- # end
|
21
|
+
- end
|
22
|
+
-
|
23
|
+
# this is quite a mess now ... I knew it would haunt me.
|
24
|
+
# to aid debugging, this online regexr can be
|
25
|
+
# used: http://rubular.com/r/DPkoE2ztpn
|
26
|
+
@@ -54,9 +47,11 @@ def all_todos
|
27
|
+
|
28
|
+
def line_number(match)
|
29
|
+
_, todo_indicator = match
|
30
|
+
+ # TODO: What if there are multiple matching lines?
|
31
|
+
GitDiffParser::Patch.new(diff.patch).changed_lines.each do |line|
|
32
|
+
return line.number if line.content =~ /#{todo_indicator}/
|
33
|
+
end
|
34
|
+
+ # TODO: thats not gonna fly
|
35
|
+
-1
|
36
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.expand_path("../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
module Danger
|
4
|
+
# rubocop:disable Metrics/BlockLength
|
5
|
+
describe Danger::MatchesInDiff do
|
6
|
+
describe "#todo_matches?" do
|
7
|
+
it "is false for no matches" do
|
8
|
+
expect(described_class.new("", []).todo_matches?).to be false
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is true for some matches" do
|
12
|
+
expect(described_class.new("", [["hey"]]).todo_matches?).to be true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#all_todos" do
|
17
|
+
it "returns the correct line number for the first todo" do
|
18
|
+
diff = sample_diff_fixture("sample_patch.diff")
|
19
|
+
subject = described_class.new(
|
20
|
+
diff,
|
21
|
+
[[
|
22
|
+
"+ #",
|
23
|
+
"TODO",
|
24
|
+
"What if there are multiple matching lines?",
|
25
|
+
"What if there are multiple matching lines?"
|
26
|
+
]]
|
27
|
+
)
|
28
|
+
expect(subject.all_todos.first.line_number).to eq 50
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns the correct line number for the second todo" do
|
32
|
+
diff = sample_diff_fixture("sample_patch.diff")
|
33
|
+
subject = described_class.new(
|
34
|
+
diff,
|
35
|
+
[[
|
36
|
+
"+ #",
|
37
|
+
"TODO",
|
38
|
+
"thats not gonna fly",
|
39
|
+
"thats not gonna fly"
|
40
|
+
]]
|
41
|
+
)
|
42
|
+
expect(subject.all_todos.first.line_number).to eq 54
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns the correct line number for a multiline todo" do
|
46
|
+
diff = sample_diff_fixture("multiline_todo_patch.diff")
|
47
|
+
subject = described_class.new(
|
48
|
+
diff,
|
49
|
+
[[
|
50
|
+
"+ #",
|
51
|
+
"TODO",
|
52
|
+
" I'd rather not have this here ...\n+ # because it's probably "\
|
53
|
+
"just a bit of code that we can reimplement\n+ # or steal",
|
54
|
+
" I'd rather not have this here ...", "\n+ # or steal"
|
55
|
+
]]
|
56
|
+
)
|
57
|
+
expect(subject.all_todos.first.line_number).to eq 22
|
58
|
+
end
|
59
|
+
|
60
|
+
it "raises when the todo string was not found in the patch" do
|
61
|
+
diff = sample_diff_fixture("sample_patch.diff")
|
62
|
+
subject = described_class.new(
|
63
|
+
diff,
|
64
|
+
[[
|
65
|
+
"+ #",
|
66
|
+
"TODO",
|
67
|
+
"",
|
68
|
+
"definately not contained in the patch"
|
69
|
+
]]
|
70
|
+
)
|
71
|
+
expect { subject.all_todos }.to raise_error(TextNotFoundInPatchError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
# rubocop:enable Metrics/BlockLength
|
76
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -80,7 +80,13 @@ end
|
|
80
80
|
def sample_diff(patch)
|
81
81
|
Git::Diff::DiffFile.new(
|
82
82
|
"base",
|
83
|
+
src: "src",
|
84
|
+
dst: "dst",
|
83
85
|
path: "some/file.rb",
|
84
86
|
patch: patch
|
85
87
|
)
|
86
88
|
end
|
89
|
+
|
90
|
+
def sample_diff_fixture(filename)
|
91
|
+
sample_diff(File.read(File.expand_path("./fixtures/#{filename}", __dir__)))
|
92
|
+
end
|
data/spec/todoist_spec.rb
CHANGED
@@ -79,10 +79,10 @@ PATCH
|
|
79
79
|
[
|
80
80
|
"#### Todos left in files",
|
81
81
|
"- some/file.rb",
|
82
|
-
" - some todo",
|
83
|
-
" - more todo in same file",
|
82
|
+
" - Line 0: some todo",
|
83
|
+
" - Line 3: more todo in same file",
|
84
84
|
"- another/stuff.rb",
|
85
|
-
" - another todo"
|
85
|
+
" - Line 0: another todo"
|
86
86
|
]
|
87
87
|
)
|
88
88
|
end
|
@@ -149,4 +149,6 @@ PATCH
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
end
|
152
|
+
# rubocop:enable Metrics/BlockLength
|
152
153
|
end
|
154
|
+
# rubocop:enable Metrics/ModuleLength
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: danger-todoist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hannes Käufler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: danger-plugin-api
|
@@ -53,75 +53,75 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: codeclimate-test-reporter
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '1.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '1.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '3.4'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '3.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '0.12'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '0.12'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '='
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.50'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.50'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: yard
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
117
|
+
version: 0.9.12
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
124
|
+
version: 0.9.12
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: guard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -199,11 +199,16 @@ files:
|
|
199
199
|
- danger-todoist.gemspec
|
200
200
|
- lib/danger_plugin.rb
|
201
201
|
- lib/danger_todoist.rb
|
202
|
+
- lib/todoist/diff_inline_todo_finder.rb
|
202
203
|
- lib/todoist/diff_todo_finder.rb
|
203
204
|
- lib/todoist/gem_version.rb
|
204
205
|
- lib/todoist/plugin.rb
|
205
206
|
- lib/todoist/todo.rb
|
207
|
+
- spec/diff_inline_todo_finder_spec.rb
|
206
208
|
- spec/diff_todo_finder_spec.rb
|
209
|
+
- spec/fixtures/multiline_todo_patch.diff
|
210
|
+
- spec/fixtures/sample_patch.diff
|
211
|
+
- spec/matches_in_diff_spec.rb
|
207
212
|
- spec/spec_helper.rb
|
208
213
|
- spec/todoist_spec.rb
|
209
214
|
homepage: https://github.com/hanneskaeufler/danger-todoist
|
@@ -232,6 +237,10 @@ specification_version: 4
|
|
232
237
|
summary: Marking something with a todo is very common during implementing a new feature.
|
233
238
|
Often those todos will get missed in code review.
|
234
239
|
test_files:
|
240
|
+
- spec/diff_inline_todo_finder_spec.rb
|
235
241
|
- spec/diff_todo_finder_spec.rb
|
242
|
+
- spec/fixtures/multiline_todo_patch.diff
|
243
|
+
- spec/fixtures/sample_patch.diff
|
244
|
+
- spec/matches_in_diff_spec.rb
|
236
245
|
- spec/spec_helper.rb
|
237
246
|
- spec/todoist_spec.rb
|