danger-periphery 0.2.0 → 0.2.2

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: 5b949d4e8279afb04d63616f89e15f3ef0efaf700b83d027273f1973d085fa23
4
- data.tar.gz: cd8e2564827d41bdee17e7b8fead197f3dc1481f129ee9dcbc22779ea1783489
3
+ metadata.gz: 1232912ce0ad696e3ea2b34b383fbc70831ccbf0a4294673a5a122c37909d677
4
+ data.tar.gz: 36c2fd6ab1f814f209cb0843db05e3d6c4bcad47360d6695db4968954048590e
5
5
  SHA512:
6
- metadata.gz: 3d0e28054ab01f50603b92cf32b6005d1befa875545afaa9d8fbd80bdf048d097776bcfcdfe01cc746a0cc24d9455284a400be7b9d11142249db9b2731d1b578
7
- data.tar.gz: 97d0f89856d52fe03fbda8f3b8539279343e2b28340042ee5db2aa2984222cf6e3ac5eacde6ad17eebc7b393f9d6163ce16f296e8a044fe984442b31566ae6ee
6
+ metadata.gz: 67cbcfbbd827ab1f276d5f0f42728cea8a38a018495bbedefd62b441fae2b6e8fd92358269fde43d2d1c8d4e14494f5c3a510dc1c51473a8ac869375d4992f25
7
+ data.tar.gz: 68d40960394c7cba16e2ae6080803b493995641548bfaa31d3f5f0b32761cb47448863c063a7ae9be6b13283682ff6c5c9d4cece0fb200dd33bb0ca17c09dac8
data/lib/danger_plugin.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "periphery"
3
+ require 'periphery'
4
4
 
5
5
  module Danger
6
6
  # Analyze Swift files and detect unused codes in your project.
7
- # This is done using [Periphery](https://github.com/peripheryapp/periphery).
7
+ # This is done using {https://github.com/peripheryapp/periphery Periphery}.
8
8
  #
9
9
  # @example Specifying options to Periphery.
10
10
  #
@@ -15,7 +15,7 @@ module Danger
15
15
  # clean_build: true
16
16
  # )
17
17
  #
18
- # @see manicmaniac/danger-periphery
18
+ # @see file:README.md
19
19
  # @tags swift
20
20
  class DangerPeriphery < Plugin
21
21
  # Path to Periphery executable.
@@ -23,6 +23,8 @@ module Danger
23
23
  # @return [String]
24
24
  attr_accessor :binary_path
25
25
 
26
+ # @deprecated Use {#scan} with block instead.
27
+ #
26
28
  # Proc object to process each warnings just before showing them.
27
29
  # The Proc must receive 4 arguments: path, line, column, message
28
30
  # and return one of:
@@ -36,78 +38,132 @@ module Danger
36
38
  #
37
39
  # By default the Proc returns true.
38
40
  # @return [Proc]
39
- attr_accessor :postprocessor
41
+ attr_reader :postprocessor
42
+
43
+ # For internal use only.
44
+ #
45
+ # @return [Symbol]
46
+ attr_writer :format
40
47
 
41
48
  OPTION_OVERRIDES = {
42
49
  disable_update_check: true,
43
- format: "checkstyle",
44
50
  quiet: true
45
51
  }.freeze
46
52
 
47
53
  def initialize(dangerfile)
48
54
  super(dangerfile)
49
- @postprocessor = ->(path, line, column, message) { true }
55
+ @postprocessor = ->(_path, _line, _column, _message) { true }
56
+ @format = :checkstyle
50
57
  end
51
58
 
52
59
  # Scans Swift files.
53
60
  # Raises an error when Periphery executable is not found.
54
61
  #
62
+ # @example Ignore all warnings from files matching regular expression
63
+ # periphery.scan do |violation|
64
+ # !violation.path.match(/.*\/generated\.swift/)
65
+ # end
66
+ #
55
67
  # @param [Hash] options Options passed to Periphery with the following translation rules.
56
68
  # 1. Replace all underscores with hyphens in each key.
57
69
  # 2. Prepend double hyphens to each key.
58
70
  # 3. If value is an array, transform it to comma-separated string.
59
71
  # 4. If value is true, drop value and treat it as option without argument.
60
- # 5. Override some options like --disable-update-check, --format, --quiet and so.
72
+ # 5. Override some options listed in {OPTION_OVERRIDES}.
73
+ # Run +$ periphery help scan+ for available options.
74
+ #
75
+ # @param [Proc] block Block to process each warning just before showing it.
76
+ # The Proc receives 1 {Periphery::ScanResult} instance as argument.
77
+ # If the Proc returns falsy value, the warning corresponding to the given ScanResult will be
78
+ # suppressed, otherwise not.
79
+ #
61
80
  # @return [void]
62
- def scan(**options, &block)
63
- output = Periphery::Runner.new(binary_path).scan(options.merge(OPTION_OVERRIDES))
81
+ def scan(options = {}, &block)
82
+ output = Periphery::Runner.new(binary_path).scan(options.merge(OPTION_OVERRIDES).merge(format: @format))
64
83
  files = files_in_diff
65
- Periphery::CheckstyleParser.new.parse(output).
66
- lazy.
67
- select { |entry| files.include?(entry.path) }.
68
- map { |entry| postprocess(entry, &block) }.
69
- force.
70
- compact.
71
- each { |path, line, column, message| warn(message, file: path, line: line) }
84
+ parser.parse(output).each do |entry|
85
+ next unless files.include?(entry.path)
86
+
87
+ result = postprocess(entry, &block)
88
+ next unless result
89
+
90
+ path, line, _column, message = result
91
+ warn(message, file: path, line: line)
92
+ end
72
93
  end
73
94
 
74
- # Convenience method to set `postprocessor` with block.
95
+ # @deprecated Use {#scan} with block instead.
75
96
  #
76
- # @return [Proc]
97
+ # Convenience method to set {#postprocessor} with block.
77
98
  #
78
- # @example Ignore all warnings from files matching regular expression
79
- # periphery.process_warnings do |path, line, column, message|
80
- # !path.match(/.*\/generated\.swift/)
81
- # end
99
+ # @return [Proc]
82
100
  def process_warnings(&block)
101
+ deprecate_in_favor_of_scan
83
102
  @postprocessor = block
84
103
  end
85
104
 
105
+ def postprocessor=(postprocessor)
106
+ deprecate_in_favor_of_scan
107
+ @postprocessor = postprocessor
108
+ end
109
+
86
110
  private
87
111
 
88
112
  def files_in_diff
89
113
  # Taken from https://github.com/ashfurrow/danger-ruby-swiftlint/blob/5184909aab00f12954088684bbf2ce5627e08ed6/lib/danger_plugin.rb#L214-L216
90
114
  renamed_files_hash = git.renamed_files.to_h { |rename| [rename[:before], rename[:after]] }
91
- post_rename_modified_files = git.modified_files.map { |modified_file| renamed_files_hash[modified_file] || modified_file }
115
+ post_rename_modified_files = git.modified_files.map do |modified_file|
116
+ renamed_files_hash[modified_file] || modified_file
117
+ end
92
118
  (post_rename_modified_files - git.deleted_files) + git.added_files
93
119
  end
94
120
 
95
121
  def postprocess(entry, &block)
96
122
  if block
97
- if block.call(entry)
98
- [entry.path, entry.line, entry.column, entry.message]
99
- end
123
+ postprocess_with_block(entry, &block)
124
+ else
125
+ postprocess_with_postprocessor(entry)
126
+ end
127
+ end
128
+
129
+ def postprocess_with_block(entry, &block)
130
+ [entry.path, entry.line, entry.column, entry.message] if block.call(entry)
131
+ end
132
+
133
+ def postprocess_with_postprocessor(entry)
134
+ result = @postprocessor.call(entry.path, entry.line, entry.column, entry.message)
135
+ if !result
136
+ nil
137
+ elsif result.is_a?(TrueClass)
138
+ [entry.path, entry.line, entry.column, entry.message]
139
+ elsif result.is_a?(Array) && result.size == 4
140
+ result
141
+ else
142
+ raise 'Proc passed to postprocessor must return one of nil, true, false and Array that includes 4 elements.'
143
+ end
144
+ end
145
+
146
+ def deprecate_in_favor_of_scan
147
+ caller_method_name = caller(1, 1)[0].sub(/.*`(.*)'.*/, '\1')
148
+ caller_location = caller_locations(2, 1)[0]
149
+ message = [
150
+ "`#{self.class}##{caller_method_name}` is deprecated; use `#{self.class}#scan` with block instead. ",
151
+ 'It will be removed from future releases.'
152
+ ].join
153
+ location_message = "#{self.class}##{caller_method_name} called from #{caller_location}"
154
+ Kernel.warn("NOTE: #{message}\n#{location_message}")
155
+ issue_reference = 'See manicmaniac/danger-periphery#37 for detail.'
156
+ warn("#{message}\n#{issue_reference}", file: caller_location.path, line: caller_location.lineno)
157
+ end
158
+
159
+ def parser
160
+ case @format
161
+ when :checkstyle
162
+ Periphery::CheckstyleParser.new
163
+ when :json
164
+ Periphery::JsonParser.new
100
165
  else
101
- result = @postprocessor.call(entry.path, entry.line, entry.column, entry.message)
102
- if !result
103
- nil
104
- elsif result.kind_of?(TrueClass)
105
- [entry.path, entry.line, entry.column, entry.message]
106
- elsif result.kind_of?(Array) && result.size == 4
107
- result
108
- else
109
- raise "Proc passed to postprocessor must return one of nil, true, false and Array that includes 4 elements."
110
- end
166
+ raise "#{@format} is unsupported"
111
167
  end
112
168
  end
113
169
  end
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "pathname"
4
- require "periphery/scan_result"
5
- require "rexml/parsers/baseparser"
6
- require "rexml/parsers/streamparser"
7
- require "rexml/streamlistener"
3
+ require 'pathname'
4
+ require 'periphery/scan_result'
5
+ require 'rexml/parsers/streamparser'
6
+ require 'rexml/streamlistener'
8
7
 
9
8
  module Periphery
9
+ # Parses {https://checkstyle.sourceforge.io/ Checkstyle} format XML produced by Periphery with
10
+ # +--format=checkstyle+ option.
10
11
  class CheckstyleParser
11
- class Listener
12
+ class Listener # :nodoc:
12
13
  include REXML::StreamListener
13
14
 
14
15
  attr_reader :results
@@ -20,22 +21,17 @@ module Periphery
20
21
 
21
22
  def tag_start(name, attrs)
22
23
  case name
23
- when "file"
24
- @current_file = relative_path(attrs["name"])
25
- when "error"
24
+ when 'file'
25
+ @current_file = relative_path(attrs['name'])
26
+ when 'error'
26
27
  if @current_file
27
- @results << ScanResult.new(
28
- @current_file,
29
- attrs["line"].to_i,
30
- attrs["column"].to_i,
31
- attrs["message"]
32
- )
28
+ @results << ScanResult.new(@current_file, attrs['line'].to_i, attrs['column'].to_i, attrs['message'])
33
29
  end
34
30
  end
35
31
  end
36
32
 
37
33
  def tag_end(name)
38
- @current_file = nil if name == "file"
34
+ @current_file = nil if name == 'file'
39
35
  end
40
36
 
41
37
  private
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'periphery/scan_result'
5
+
6
+ module Periphery
7
+ # Parses JSON formatted output produced by Periphery with +--format=json+ option.
8
+ class JsonParser
9
+ def parse(string)
10
+ JSON.parse(string).map do |entry|
11
+ path, line, column = parse_location(entry['location'])
12
+ message = compose_message(*entry.slice('name', 'kind', 'hints').values)
13
+ ScanResult.new(path, line, column, message)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def relative_path(path, base = Pathname.getwd)
20
+ Pathname.new(path).relative_path_from(base).to_s
21
+ end
22
+
23
+ # Parses a string like '/path/to/file.swift:19:10'
24
+ def parse_location(location)
25
+ location.scan(/^(.+):(\d+):(\d+)$/) do |path, line, column|
26
+ return [relative_path(path), line.to_i, column.to_i]
27
+ end
28
+ raise ArgumentError, "#{location} is not in a valid format"
29
+ end
30
+
31
+ def compose_message(name, kind, hints)
32
+ return 'unused' unless name
33
+
34
+ # Assumes hints contains only one item.
35
+ # https://github.com/peripheryapp/periphery/blob/2.9.0/Sources/Frontend/Formatters/JsonFormatter.swift#L27
36
+ # https://github.com/peripheryapp/periphery/blob/2.9.0/Sources/Frontend/Formatters/JsonFormatter.swift#L42
37
+ hint = hints[0]
38
+ +"#{display_name(kind).capitalize} '#{name}' #{describe_hint(hint)}"
39
+ end
40
+
41
+ def display_name(kind)
42
+ case kind
43
+ when 'enumelement' then 'enum case'
44
+ when 'function.constructor' then 'initializer'
45
+ when 'var.parameter' then 'parameter'
46
+ when 'generic_type_param' then 'generic type parameter'
47
+ when nil then ''
48
+ else kind.start_with?('var') ? 'property' : kind.split('.', 2)[0]
49
+ end
50
+ end
51
+
52
+ def describe_hint(hint)
53
+ case hint
54
+ when 'unused' then 'is unused'
55
+ when 'assignOnlyProperty' then 'is assigned, but never used'
56
+ when 'redundantProtocol' then "is redundant as it's never used as an existential type"
57
+ when 'redundantConformance' then 'conformance is redundant'
58
+ # FIXME: There's no information about the name of module in JSON output,
59
+ # unlike other formatters can output `outside of FooModule`.
60
+ # This is known problem and may be fixed in future Periphery's release.
61
+ # See the status of https://github.com/peripheryapp/periphery/pull/519
62
+ when 'redundantPublicAccessibility' then 'is declared public, but not used outside of the module'
63
+ else ''
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,35 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "open3"
3
+ require 'open3'
4
4
 
5
5
  module Periphery
6
- class Runner
6
+ class Runner # :nodoc:
7
7
  attr_reader :binary_path
8
8
 
9
9
  def initialize(binary_path)
10
- @binary_path = binary_path || "periphery"
10
+ @binary_path = binary_path || 'periphery'
11
11
  end
12
12
 
13
13
  def scan(options)
14
- arguments = [binary_path, "scan"] + scan_arguments(options)
14
+ arguments = [binary_path, 'scan'] + scan_arguments(options)
15
15
  stdout, stderr, status = Open3.capture3(*arguments)
16
- if status.success?
17
- stdout
18
- else
19
- raise "error: #{arguments} exited with status code #{status.exitstatus}. #{stderr}" unless status.success?
20
- end
16
+ raise "error: #{arguments} exited with status code #{status.exitstatus}. #{stderr}" unless status.success?
17
+
18
+ stdout
21
19
  end
22
20
 
23
21
  def scan_arguments(options)
24
- options.
25
- lazy.
26
- select { |_key, value| value }.
27
- map { |key, value| value.kind_of?(TrueClass) ? [key, nil] : [key, value] }.
28
- map { |key, value| value.kind_of?(Array) ? [key, value.join(",")] : [key, value] }.
29
- map { |key, value| ["--#{key.to_s.tr('_', '-')}", value&.to_s] }.
30
- force.
31
- flatten.
32
- compact
22
+ options.each_with_object([]) do |(key, value), new_options|
23
+ next unless value
24
+
25
+ value = nil if value.is_a?(TrueClass)
26
+ value = value.join(',') if value.is_a?(Array)
27
+ new_options << "--#{key.to_s.tr('_', '-')}"
28
+ new_options << value&.to_s if value
29
+ end
33
30
  end
34
31
  end
35
32
  end
data/lib/periphery.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "periphery/runner"
4
- require "periphery/checkstyle_parser"
3
+ require 'periphery/runner'
4
+ require 'periphery/checkstyle_parser'
5
+ require 'periphery/json_parser'
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DangerPeriphery
4
- VERSION = "0.2.0"
4
+ VERSION = '0.2.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danger-periphery
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryosuke Ito
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-22 00:00:00.000000000 Z
11
+ date: 2022-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: danger-plugin-api
@@ -27,39 +27,17 @@ dependencies:
27
27
  description: A Danger plugin to detect unused codes.
28
28
  email:
29
29
  - rito.0305@gmail.com
30
- executables:
31
- - download_periphery
30
+ executables: []
32
31
  extensions: []
33
32
  extra_rdoc_files: []
34
33
  files:
35
- - ".github/workflows/lint.yml"
36
- - ".github/workflows/test.yml"
37
- - ".gitignore"
38
- - ".rspec"
39
- - ".rubocop.yml"
40
- - Dangerfile
41
- - Gemfile
42
- - Gemfile.lock
43
- - Guardfile
44
- - LICENSE.txt
45
- - README.md
46
- - Rakefile
47
- - bin/download_periphery
48
- - danger-periphery.gemspec
49
34
  - lib/danger_plugin.rb
50
35
  - lib/periphery.rb
51
36
  - lib/periphery/checkstyle_parser.rb
37
+ - lib/periphery/json_parser.rb
52
38
  - lib/periphery/runner.rb
53
39
  - lib/periphery/scan_result.rb
54
40
  - lib/version.rb
55
- - spec/danger_plugin_spec.rb
56
- - spec/periphery/checkstyle_parser_spec.rb
57
- - spec/periphery/runner_spec.rb
58
- - spec/spec_helper.rb
59
- - spec/support/fixtures/github_pr.json
60
- - spec/support/fixtures/mock-periphery
61
- - spec/support/fixtures/test.xcodeproj/project.pbxproj
62
- - spec/support/fixtures/test/main.swift
63
41
  homepage: https://github.com/manicmaniac/danger-periphery
64
42
  licenses:
65
43
  - MIT
@@ -80,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
58
  - !ruby/object:Gem::Version
81
59
  version: '0'
82
60
  requirements: []
83
- rubygems_version: 3.0.3.1
61
+ rubygems_version: 3.1.2
84
62
  signing_key:
85
63
  specification_version: 4
86
64
  summary: A Danger plugin to detect unused codes.
@@ -1,12 +0,0 @@
1
- name: Lint
2
- on: [pull_request]
3
- jobs:
4
- lint:
5
- runs-on: macOS-11
6
- env:
7
- DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
8
- steps:
9
- - uses: actions/checkout@v2
10
- - run: bin/download_periphery
11
- - run: bundle install
12
- - run: bundle exec danger
@@ -1,10 +0,0 @@
1
- name: Test
2
- on: [push]
3
- jobs:
4
- unit-test:
5
- runs-on: macOS-11
6
- steps:
7
- - uses: actions/checkout@v2
8
- - run: bin/download_periphery
9
- - run: bundle install
10
- - run: bundle exec rake
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- .DS_Store
2
- .idea/
3
- .yardoc
4
- /tmp
5
- bin/lib_InternalSwiftSyntaxParser.dylib
6
- bin/periphery
7
- pkg
8
- project.xcworkspace
9
- xcuserdata
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --color
2
- --require spec_helper
3
- --format documentation