debtective 0.2.3.2 → 0.2.3.3

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: 1dbc3a3e7ee53fc04a2759fcf0e538773d2e03633e8d8770b536c6ce49d81466
4
- data.tar.gz: 3ae9df343e6cee84e979ccc66fe35fda106df0a69bf2c6c570cdfb76f92859f3
3
+ metadata.gz: f5c39390d5b43a335045481e47b106c30facd0d66ea88359209ecc57887f6a4e
4
+ data.tar.gz: 182beede8ace506b42e175bdd9fec0748464bfe4aa75ff1e95c7d100df4c5444
5
5
  SHA512:
6
- metadata.gz: 0c1e6dacb2bbf1b23102add21f05f1872700ac71975b20e7fc70f1078e2a8faef5a3c4ac8daad30047e1e46ae287fac178c6916e7e4a54439ea1085f589a7155
7
- data.tar.gz: ed2f39253ec62220a150e7639628f2e8420375b7fef444a0c2d4f8bdd1f4a65f62449d9f7ab968001cada37fc57aaec80097931aebb259f61d09fa3943cbf3fb
6
+ metadata.gz: c846a7c047b667926d576a51331820b26e98d8e25ff16bdb192a2c8aa080aceac69f9cb7f747c90d8e3c25ed6c7c59bd3fbd6642a2da2572ffeeb304c54aa10d
7
+ data.tar.gz: 4870ac4fcc0b9fa93eeaf2f72e410b06bd7b9bcea56e44557f32ee2788c572186cdea8177a6168c24cc6917360e5d02e90793b951d5d1bcdb58806cad00ca28b
data/bin/debtective CHANGED
@@ -2,7 +2,6 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "debtective"
5
- require "debtective/output_todos"
6
5
 
7
6
  user_name =
8
7
  if ARGV.include?("--me")
@@ -11,11 +10,14 @@ user_name =
11
10
  ARGV[ARGV.index("--user") + 1]
12
11
  end
13
12
 
14
- if user_name
15
- puts "Searching TODOs from #{user_name}..."
13
+ quiet = ARGV.include?("--quiet")
14
+
15
+ case ARGV[0]
16
+ when "--todos"
17
+ require "debtective/todos/output"
18
+ Debtective::Todos::Output.new(user_name, quiet: quiet).call
19
+ when "--offenses", "--gems"
20
+ puts "Upcoming feature"
16
21
  else
17
- puts "Searching TODOs..."
22
+ puts "Please pass one of this options: [--todos, --offenses, --gems]"
18
23
  end
19
-
20
- quiet = ARGV.include?("--quiet")
21
- Debtective::OutputTodos.new(user_name, quiet: quiet).call
@@ -5,7 +5,7 @@ require "open3"
5
5
 
6
6
  module Debtective
7
7
  # find the commit that introduced a line of code
8
- class GitCommit
8
+ class FindCommit
9
9
  Author = Struct.new(:email, :name)
10
10
  Commit = Struct.new(:sha, :author, :time)
11
11
 
@@ -18,7 +18,7 @@ module Debtective
18
18
  @code = code
19
19
  end
20
20
 
21
- # @return [Debtective::GitCommit::Commit]
21
+ # @return [Debtective::FindCommit::Commit]
22
22
  def call
23
23
  Commit.new(sha, author, time)
24
24
  rescue Git::GitExecuteError
@@ -26,7 +26,7 @@ module Debtective
26
26
  Commit.new(nil, author, nil)
27
27
  end
28
28
 
29
- # @return [Debtective::GitCommit::Author]
29
+ # @return [Debtective::FindCommit::Author]
30
30
  def author
31
31
  Author.new(commit.author.email, commit.author.name)
32
32
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "debtective/todos/todo"
5
+ require "debtective/find_end_of_statement"
6
+
7
+ module Debtective
8
+ module Todos
9
+ # Find the todos comments and their boundaries
10
+ class Build
11
+ BEFORE_LINE_TODO_REGEX = /^\s*#\sTODO:\s/
12
+ INLINE_TODO_REGEX = /\s*#\sTODO:\s/
13
+ COMMENT_REGEX = /\s*#/
14
+
15
+ # @param pathname [Pathname]
16
+ # @param index [Integer]
17
+ def initialize(pathname, index)
18
+ @pathname = pathname
19
+ @index = index
20
+ end
21
+
22
+ # @return [Debtective::Todos::Todo]
23
+ def call
24
+ Debtective::Todos::Todo.new(
25
+ @pathname,
26
+ lines,
27
+ todo_boundaries,
28
+ statement_boundaries
29
+ )
30
+ end
31
+
32
+ private
33
+
34
+ # @return [Array<String>]
35
+ def lines
36
+ @lines ||= @pathname.readlines
37
+ end
38
+
39
+ # @return [Range]
40
+ def todo_boundaries
41
+ @index..([@index, statement_boundaries.min - 1].max)
42
+ end
43
+
44
+ # range of the concerned code
45
+ # @return [Range]
46
+ def statement_boundaries
47
+ @statement_boundaries ||=
48
+ case lines[@index]
49
+ when BEFORE_LINE_TODO_REGEX
50
+ first_line_index = statement_start
51
+ last_line_index = Debtective::FindEndOfStatement.new(lines, first_line_index).call
52
+ first_line_index..last_line_index
53
+ when INLINE_TODO_REGEX
54
+ @index..@index
55
+ end
56
+ end
57
+
58
+ # start index of the concerned code (i.e. below the TODO comment)
59
+ # @return [Integer]
60
+ def statement_start
61
+ lines.index.with_index do |line, i|
62
+ i > @index &&
63
+ !line.strip.empty? &&
64
+ !line.match?(COMMENT_REGEX)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "debtective/todos/build"
5
+
6
+ module Debtective
7
+ module Todos
8
+ # Find and investigate todo comments and return a list of todos
9
+ class Find
10
+ TODO_REGEX = /#\sTODO:/
11
+
12
+ # @param paths [Array<String>]
13
+ def initialize(paths)
14
+ @paths = paths
15
+ end
16
+
17
+ # @return [Array<Debtective::Todos::Todo>]
18
+ def call
19
+ ruby_pathnames.flat_map { pathname_todos(_1) }
20
+ end
21
+
22
+ private
23
+
24
+ # @return [Array<Pathname>] only pathes to ruby files
25
+ def ruby_pathnames
26
+ @paths
27
+ .flat_map { Dir[_1] }
28
+ .map { Pathname(_1) }
29
+ .select { _1.file? && _1.extname == ".rb" }
30
+ end
31
+
32
+ # return todos in the pathname
33
+ # @return [Array<Debtective::Todos::Todo>]
34
+ def pathname_todos(pathname)
35
+ pathname.readlines.filter_map.with_index do |line, index|
36
+ next unless line.match?(TODO_REGEX)
37
+
38
+ Debtective::Todos::Todo.build(pathname, index)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "debtective/todos/find"
4
+
5
+ module Debtective
6
+ module Todos
7
+ # Information about the todos in the codebase
8
+ class List
9
+ Author = Struct.new(:email, :name, :todos)
10
+
11
+ # @param paths [Array<String>]
12
+ def initialize(paths)
13
+ @paths = paths
14
+ end
15
+
16
+ # @return [Array<Debtective::Todos::Todo>]
17
+ def todos
18
+ @todos ||= Debtective::Todos::Find.new(@paths).call
19
+ end
20
+
21
+ # @return [Array<Debtective::Todos::List::Author>]
22
+ def authors
23
+ todos
24
+ .map { [_1.commit.author.email, _1.commit.author.name] }
25
+ .uniq
26
+ .map { author(_1) }
27
+ end
28
+
29
+ # @return [Integer]
30
+ def extended_count
31
+ todos.sum(&:size)
32
+ end
33
+
34
+ # @return [Integer]
35
+ def combined_count
36
+ todos
37
+ .group_by(&:pathname)
38
+ .values
39
+ .sum do |pathname_todos|
40
+ pathname_todos
41
+ .map { _1.statement_boundaries.to_a }
42
+ .reduce(:|)
43
+ .length
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # @param email_and_name [Array<String>]
50
+ # @return [Debtective::Todos::List::Author]
51
+ def author(email_and_name)
52
+ Author.new(
53
+ *email_and_name,
54
+ todos.select { email_and_name == [_1.commit.author.email, _1.commit.author.name] }
55
+ )
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "debtective/todos/print_table"
5
+
6
+ module Debtective
7
+ module Todos
8
+ # Generate todolist
9
+ class Output
10
+ FILE_PATH = "todos.json"
11
+
12
+ # @param user_name [String] git user email to filter
13
+ def initialize(user_name = nil, quiet: false)
14
+ @user_name = user_name
15
+ @quiet = quiet
16
+ end
17
+
18
+ # @return [void]
19
+ def call
20
+ @list = log_table
21
+ @list ||= Debtective::Todos::List.new(Debtective.configuration&.paths || ["./**/*"])
22
+ filter_list!
23
+ log_counts
24
+ update_json_file
25
+ return if @quiet
26
+
27
+ puts FILE_PATH
28
+ end
29
+
30
+ private
31
+
32
+ # @return [void]
33
+ def log_table
34
+ return if @quiet
35
+
36
+ Debtective::Todos::PrintTable.new(@user_name).call
37
+ end
38
+
39
+ # @return [void]
40
+ def filter_list!
41
+ !@user_name.nil? && @list.todos.select! { _1.commit.author.name == @user_name }
42
+ end
43
+
44
+ # @return [void]
45
+ def log_counts
46
+ return if @quiet
47
+
48
+ puts "total: #{@list.todos.count}"
49
+ puts "combined lines count: #{@list.combined_count}"
50
+ puts "extended lines count: #{@list.extended_count}"
51
+ end
52
+
53
+ # @return [void]
54
+ def update_json_file
55
+ File.open(FILE_PATH, "w") do |file|
56
+ file.puts(
57
+ JSON.pretty_generate(
58
+ @list.todos.map(&:to_h)
59
+ )
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "debtective/todos/list"
4
+
5
+ module Debtective
6
+ module Todos
7
+ # Print todos as a table in the stdout
8
+ class PrintTable
9
+ # @param user_name [String] git user email to filter
10
+ def initialize(user_name = nil)
11
+ @user_name = user_name
12
+ end
13
+
14
+ # @return [Debtective::Todos::List]
15
+ def call
16
+ log_table_headers
17
+ log_table_rows
18
+ list
19
+ end
20
+
21
+ private
22
+
23
+ # @return [void]
24
+ def log_table_headers
25
+ puts separator
26
+ puts table_row("location", "author", "days", "size")
27
+ puts separator
28
+ end
29
+
30
+ # @return [void]
31
+ def log_table_rows
32
+ trace.enable
33
+ list.todos
34
+ trace.disable
35
+ puts separator
36
+ end
37
+
38
+ # use a trace to log each todo as soon as it is found
39
+ # @return [Tracepoint]
40
+ def trace
41
+ TracePoint.new(:return) do |trace_point|
42
+ next unless trace_point.defined_class == Debtective::Todos::Build && trace_point.method_id == :call
43
+
44
+ todo = trace_point.return_value
45
+ log_todo(todo)
46
+ end
47
+ end
48
+
49
+ # if a user_name is given and is not the commit author
50
+ # the line is temporary and will be replaced by the next one
51
+ # @return [void]
52
+ def log_todo(todo)
53
+ row = table_row(
54
+ todo.location,
55
+ todo.commit.author.name || "?",
56
+ todo.days || "?",
57
+ todo.size
58
+ )
59
+ if @user_name.nil? || @user_name == todo.commit.author.name
60
+ puts row
61
+ else
62
+ print "#{row}\r"
63
+ end
64
+ end
65
+
66
+ # @return [Debtective::Todos::Todo]
67
+ def list
68
+ @list ||= Debtective::Todos::List.new(
69
+ Debtective.configuration&.paths || ["./**/*"]
70
+ )
71
+ end
72
+
73
+ # @return [String]
74
+ def table_row(location, author, days, size)
75
+ [
76
+ format("%-80.80s", location),
77
+ format("%-20.20s", author),
78
+ format("%-12.12s", days),
79
+ format("%-12.12s", size)
80
+ ].join(" | ")
81
+ end
82
+
83
+ # @return [String]
84
+ def separator
85
+ @separator ||= Array.new(table_row(nil, nil, nil, nil).size) { "-" }.join
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "debtective/find_commit"
4
+
5
+ module Debtective
6
+ module Todos
7
+ # Hold todo information
8
+ class Todo
9
+ class << self
10
+ # @return [Debtective::Todos::Todo]
11
+ def build(pathname, index)
12
+ Build.new(pathname, index).call
13
+ end
14
+ end
15
+
16
+ attr_accessor :pathname, :todo_boundaries, :statement_boundaries
17
+
18
+ # @param pathname [Pathname]
19
+ # @param lines [Array<String>]
20
+ # @param todo_boundaries [Range]
21
+ # @param statement_boundaries [Range]
22
+ def initialize(pathname, lines, todo_boundaries, statement_boundaries)
23
+ @pathname = pathname
24
+ @lines = lines
25
+ @todo_boundaries = todo_boundaries
26
+ @statement_boundaries = statement_boundaries
27
+ end
28
+
29
+ # location in the codebase
30
+ # @return [String]
31
+ def location
32
+ "#{@pathname}:#{@todo_boundaries.min + 1}"
33
+ end
34
+
35
+ # size of the todo code
36
+ # @return [Integer]
37
+ def size
38
+ @statement_boundaries.size
39
+ end
40
+
41
+ # return commit that introduced the todo
42
+ # @return [Git::Object::Commit]
43
+ def commit
44
+ @commit ||= Debtective::FindCommit.new(@pathname, @lines[@todo_boundaries.min]).call
45
+ end
46
+
47
+ # @return [Integer]
48
+ def days
49
+ return if commit.time.nil?
50
+
51
+ ((Time.now - commit.time) / (24 * 60 * 60)).round
52
+ end
53
+
54
+ # @return [Hash]
55
+ def to_h
56
+ {
57
+ pathname: pathname,
58
+ location: location,
59
+ todo_boundaries: todo_boundaries.minmax,
60
+ statement_boundaries: statement_boundaries.minmax,
61
+ size: size,
62
+ commit: {
63
+ sha: commit.sha,
64
+ author: commit.author.to_h,
65
+ time: commit.time
66
+ }
67
+ }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Debtective
4
- VERSION = "0.2.3.2"
4
+ VERSION = "0.2.3.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debtective
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.2
4
+ version: 0.2.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Piron
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-16 00:00:00.000000000 Z
11
+ date: 2023-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -118,19 +118,18 @@ extra_rdoc_files: []
118
118
  files:
119
119
  - bin/debtective
120
120
  - lib/debtective.rb
121
- - lib/debtective/build_todo.rb
122
121
  - lib/debtective/configuration.rb
122
+ - lib/debtective/find_commit.rb
123
123
  - lib/debtective/find_end_of_statement.rb
124
- - lib/debtective/find_todos.rb
125
- - lib/debtective/git_commit.rb
126
- - lib/debtective/output_todos.rb
127
- - lib/debtective/print_table.rb
128
124
  - lib/debtective/railtie.rb
129
125
  - lib/debtective/stderr_helper.rb
130
- - lib/debtective/todo.rb
131
- - lib/debtective/todo_list.rb
126
+ - lib/debtective/todos/build.rb
127
+ - lib/debtective/todos/find.rb
128
+ - lib/debtective/todos/list.rb
129
+ - lib/debtective/todos/output.rb
130
+ - lib/debtective/todos/print_table.rb
131
+ - lib/debtective/todos/todo.rb
132
132
  - lib/debtective/version.rb
133
- - lib/tasks/debtective/todo_list.rake
134
133
  homepage: https://github.com/BigBigDoudou/debtective
135
134
  licenses:
136
135
  - MIT
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
- require "debtective/todo"
5
- require "debtective/find_end_of_statement"
6
-
7
- module Debtective
8
- # Find the todos comments and their boundaries
9
- class BuildTodo
10
- BEFORE_LINE_TODO_REGEX = /^\s*#\sTODO:\s/
11
- INLINE_TODO_REGEX = /\s*#\sTODO:\s/
12
- COMMENT_REGEX = /\s*#/
13
-
14
- # @param pathname [Pathname]
15
- # @param index [Integer]
16
- def initialize(pathname, index)
17
- @pathname = pathname
18
- @index = index
19
- end
20
-
21
- # @return [Debtective::Todo]
22
- def call
23
- Todo.new(
24
- @pathname,
25
- lines,
26
- todo_boundaries,
27
- statement_boundaries
28
- )
29
- end
30
-
31
- private
32
-
33
- # @return [Array<String>]
34
- def lines
35
- @lines ||= @pathname.readlines
36
- end
37
-
38
- # @return [Range]
39
- def todo_boundaries
40
- @index..([@index, statement_boundaries.min - 1].max)
41
- end
42
-
43
- # range of the concerned code
44
- # @return [Range]
45
- def statement_boundaries
46
- @statement_boundaries ||=
47
- case lines[@index]
48
- when BEFORE_LINE_TODO_REGEX
49
- first_line_index = statement_start
50
- last_line_index = FindEndOfStatement.new(lines, first_line_index).call
51
- first_line_index..last_line_index
52
- when INLINE_TODO_REGEX
53
- @index..@index
54
- end
55
- end
56
-
57
- # start index of the concerned code (i.e. below the TODO comment)
58
- # @return [Integer]
59
- def statement_start
60
- lines.index.with_index do |line, i|
61
- i > @index &&
62
- !line.strip.empty? &&
63
- !line.match?(COMMENT_REGEX)
64
- end
65
- end
66
- end
67
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
- require "debtective/build_todo"
5
-
6
- module Debtective
7
- # Find and investigate todo comments and return a list of todos
8
- class FindTodos
9
- TODO_REGEX = /#\sTODO:/
10
-
11
- # @param paths [Array<String>]
12
- def initialize(paths)
13
- @paths = paths
14
- end
15
-
16
- # @return [Array<Debtective::Todo>]
17
- def call
18
- ruby_pathnames.flat_map { pathname_todos(_1) }
19
- end
20
-
21
- private
22
-
23
- # @return [Array<Pathname>] only pathes to ruby files
24
- def ruby_pathnames
25
- @paths
26
- .flat_map { Dir[_1] }
27
- .map { Pathname(_1) }
28
- .select { _1.file? && _1.extname == ".rb" }
29
- end
30
-
31
- # return todos in the pathname
32
- # @return [Array<Debtective::Todo>]
33
- def pathname_todos(pathname)
34
- pathname.readlines.filter_map.with_index do |line, index|
35
- next unless line.match?(TODO_REGEX)
36
-
37
- Todo.build(pathname, index)
38
- end
39
- end
40
- end
41
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require "debtective/print_table"
5
- require "pry"
6
-
7
- module Debtective
8
- # Generate todolist
9
- class OutputTodos
10
- FILE_PATH = "todos.json"
11
-
12
- # @param user_name [String] git user email to filter
13
- def initialize(user_name = nil, quiet: false)
14
- @user_name = user_name
15
- @quiet = quiet
16
- end
17
-
18
- # @return [void]
19
- def call
20
- @todo_list = log_table
21
- @todo_list ||= Debtective::TodoList.new(Debtective.configuration&.paths || ["./**/*"])
22
- filter_todo_list!
23
- log_counts
24
- update_json_file
25
- puts FILE_PATH
26
- end
27
-
28
- private
29
-
30
- # @return [void]
31
- def log_table
32
- return if @quiet
33
-
34
- Debtective::PrintTable.new(@user_name).call
35
- end
36
-
37
- # @return [void]
38
- def filter_todo_list!
39
- !@user_name.nil? && @todo_list.todos.select! { _1.commit.author.name == @user_name }
40
- end
41
-
42
- # @return [void]
43
- def log_counts
44
- @return if @quiet
45
-
46
- puts "total: #{@todo_list.todos.count}"
47
- puts "combined lines count: #{@todo_list.combined_count}"
48
- puts "extended lines count: #{@todo_list.extended_count}"
49
- end
50
-
51
- # @return [void]
52
- def update_json_file
53
- File.open(FILE_PATH, "w") do |file|
54
- file.puts(
55
- JSON.pretty_generate(
56
- @todo_list.todos.map(&:to_h)
57
- )
58
- )
59
- end
60
- end
61
- end
62
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "debtective/todo_list"
4
-
5
- module Debtective
6
- # Print todos as a table in the stdout
7
- class PrintTable
8
- # @param user_name [String] git user email to filter
9
- def initialize(user_name = nil)
10
- @user_name = user_name
11
- end
12
-
13
- # @return [Debtective::TodoList]
14
- def call
15
- log_table_headers
16
- log_table_rows
17
- todo_list
18
- end
19
-
20
- private
21
-
22
- # @return [void]
23
- def log_table_headers
24
- puts separator
25
- puts table_row("location", "author", "days", "size")
26
- puts separator
27
- end
28
-
29
- # @return [void]
30
- def log_table_rows
31
- trace.enable
32
- todo_list.todos
33
- trace.disable
34
- puts separator
35
- end
36
-
37
- # use a trace to log each todo as soon as it is found
38
- # @return [Tracepoint]
39
- def trace
40
- TracePoint.new(:return) do |trace_point|
41
- next unless trace_point.defined_class == Debtective::BuildTodo && trace_point.method_id == :call
42
-
43
- todo = trace_point.return_value
44
- log_todo(todo)
45
- end
46
- end
47
-
48
- # if a user_name is given and is not the commit author
49
- # the line is temporary and will be replaced by the next one
50
- # @return [void]
51
- def log_todo(todo)
52
- row = table_row(
53
- todo.location,
54
- todo.commit.author.name || "?",
55
- todo.days || "?",
56
- todo.size
57
- )
58
- if @user_name.nil? || @user_name == todo.commit.author.name
59
- puts row
60
- else
61
- print "#{row}\r"
62
- end
63
- end
64
-
65
- # @return [Debtective::Todo]
66
- def todo_list
67
- @todo_list ||= Debtective::TodoList.new(
68
- Debtective.configuration&.paths || ["./**/*"]
69
- )
70
- end
71
-
72
- # @return [String]
73
- def table_row(location, author, days, size)
74
- [
75
- format("%-80.80s", location),
76
- format("%-20.20s", author),
77
- format("%-12.12s", days),
78
- format("%-12.12s", size)
79
- ].join(" | ")
80
- end
81
-
82
- # @return [String]
83
- def separator
84
- @separator ||= Array.new(table_row(nil, nil, nil, nil).size) { "-" }.join
85
- end
86
- end
87
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "debtective/git_commit"
4
-
5
- module Debtective
6
- # Hold todo information
7
- class Todo
8
- class << self
9
- # @return [Debtective::Todo]
10
- def build(pathname, index)
11
- BuildTodo.new(pathname, index).call
12
- end
13
- end
14
-
15
- attr_accessor :pathname, :todo_boundaries, :statement_boundaries
16
-
17
- # @param pathname [Pathname]
18
- # @param lines [Array<String>]
19
- # @param todo_boundaries [Range]
20
- # @param statement_boundaries [Range]
21
- def initialize(pathname, lines, todo_boundaries, statement_boundaries)
22
- @pathname = pathname
23
- @lines = lines
24
- @todo_boundaries = todo_boundaries
25
- @statement_boundaries = statement_boundaries
26
- end
27
-
28
- # location in the codebase
29
- # @return [String]
30
- def location
31
- "#{@pathname}:#{@todo_boundaries.min + 1}"
32
- end
33
-
34
- # size of the todo code
35
- # @return [Integer]
36
- def size
37
- @statement_boundaries.size
38
- end
39
-
40
- # return commit that introduced the todo
41
- # @return [Git::Object::Commit]
42
- def commit
43
- @commit ||= Debtective::GitCommit.new(@pathname, @lines[@todo_boundaries.min]).call
44
- end
45
-
46
- # @return [Integer]
47
- def days
48
- return if commit.time.nil?
49
-
50
- ((Time.now - commit.time) / (24 * 60 * 60)).round
51
- end
52
-
53
- # @return [Hash]
54
- def to_h
55
- {
56
- pathname: pathname,
57
- location: location,
58
- todo_boundaries: todo_boundaries.minmax,
59
- statement_boundaries: statement_boundaries.minmax,
60
- size: size,
61
- commit: {
62
- sha: commit.sha,
63
- author: commit.author.to_h,
64
- time: commit.time
65
- }
66
- }
67
- end
68
- end
69
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "debtective/find_todos"
4
-
5
- module Debtective
6
- # Information about the todos in the codebase
7
- class TodoList
8
- Author = Struct.new(:email, :name, :todos)
9
-
10
- # @param paths [Array<String>]
11
- def initialize(paths)
12
- @paths = paths
13
- end
14
-
15
- # @return [Array<Debtective::Todo>]
16
- def todos
17
- @todos ||= Debtective::FindTodos.new(@paths).call
18
- end
19
-
20
- # @return [Array<TodoList::Author>]
21
- def authors
22
- todos
23
- .map { [_1.commit.author.email, _1.commit.author.name] }
24
- .uniq
25
- .map { author(_1) }
26
- end
27
-
28
- # @return [Integer]
29
- def extended_count
30
- todos.sum(&:size)
31
- end
32
-
33
- # @return [Integer]
34
- def combined_count
35
- todos
36
- .group_by(&:pathname)
37
- .values
38
- .sum do |pathname_todos|
39
- pathname_todos
40
- .map { _1.statement_boundaries.to_a }
41
- .reduce(:|)
42
- .length
43
- end
44
- end
45
-
46
- private
47
-
48
- # @param email_and_name [Array<String>]
49
- # @return [TodoList::Author]
50
- def author(email_and_name)
51
- Author.new(
52
- *email_and_name,
53
- todos.select { email_and_name == [_1.commit.author.email, _1.commit.author.name] }
54
- )
55
- end
56
- end
57
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "debtective/output_todos"
4
-
5
- begin
6
- require "#{Rails.root}/config/initializers/debtective" if defined?(Rails)
7
- rescue LoadError
8
- nil
9
- end
10
-
11
- namespace :debtective do
12
- desc "Todo List"
13
- task :todo_list do
14
- user_name =
15
- if ARGV.include?("--me")
16
- `git config user.name`.strip
17
- elsif ARGV.include?("--user")
18
- ARGV[ARGV.index("--user") + 1]
19
- end
20
-
21
- if user_name
22
- puts "Searching TODOs from #{user_name}..."
23
- else
24
- puts "Searching TODOs..."
25
- end
26
-
27
- Debtective::OutputTodos.new(user_name, quiet: ARGV.include?("--quiet")).call
28
- end
29
- end