danger-periphery 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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