xclinter 0.9.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 +7 -0
- data/bin/console +14 -0
- data/bin/setup +6 -0
- data/bin/xclinter +7 -0
- data/lib/xclinter/version.rb +3 -0
- data/lib/xclinter.rb +204 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9e55a275c71738e4324735eebba7a7958863f92a
|
4
|
+
data.tar.gz: ab341c95860d7c1a7b8dea3c0c2758ea1b8c8cfe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5a5e8117e213db902c0c7f173b25f9fd6a1186f402413a3d1927d1c67df4df780f83eaa091885d7a62f2e3226e18d3eee032bbe51a75326f95df98628578f3ed
|
7
|
+
data.tar.gz: f30588cc80d70a20c7d3d0c3a9f3e802e73ad033b4bc2e31354ccf97b69bdffccbcaf67104e1f29b95114487948a4b19bfe5bf4925323b90a083d0a80f079e69
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "xclinter"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/bin/xclinter
ADDED
data/lib/xclinter.rb
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
require "xclinter/version"
|
2
|
+
require "thor"
|
3
|
+
require "xcodeproj"
|
4
|
+
|
5
|
+
module Xclinter
|
6
|
+
class Xclinter < Thor
|
7
|
+
package_name "Xclinter"
|
8
|
+
|
9
|
+
desc "lintAll", "Runs all linters"
|
10
|
+
options :project => :string, :target => :string
|
11
|
+
def lintAll
|
12
|
+
project = getProject(options)
|
13
|
+
target = getTarget(options, project)
|
14
|
+
|
15
|
+
stringFiles = stringsFiles(target)
|
16
|
+
imageNamesUsed = imageNamesUsed(target)
|
17
|
+
images = images(target)
|
18
|
+
|
19
|
+
exitcode = 0
|
20
|
+
|
21
|
+
exitcode += lintStringFilesHelper(stringFiles)
|
22
|
+
exitcode += lintImageLiteralsHelper(images, imageNamesUsed)
|
23
|
+
exitcode += findUnusedImagesHelper(images, imageNamesUsed)
|
24
|
+
|
25
|
+
exit exitcode
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "lintStringFiles", "Lints Strings files for missing semicolons etc."
|
29
|
+
options :project => :string, :target => :string
|
30
|
+
def lintStringFiles
|
31
|
+
project = getProject(options)
|
32
|
+
target = getTarget(options, project)
|
33
|
+
|
34
|
+
stringFiles = stringsFiles(target)
|
35
|
+
|
36
|
+
exit lintStringFilesHelper(stringFiles)
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "lintImageLiterals", "Lints code for imageLiterals with non existing images "
|
40
|
+
options :project => :string, :target => :string
|
41
|
+
def lintImageLiterals
|
42
|
+
project = getProject(options)
|
43
|
+
target = getTarget(options, project)
|
44
|
+
|
45
|
+
imageNamesUsed = imageNamesUsed(target)
|
46
|
+
images = images(target)
|
47
|
+
|
48
|
+
exit lintImageLiteralsHelper(images, imageNamesUsed)
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "findUnusedImages", "Lints code for images not used in any imageLiterals"
|
52
|
+
options :project => :string, :target => :string
|
53
|
+
def findUnusedImages
|
54
|
+
project = getProject(options)
|
55
|
+
target = getTarget(options, project)
|
56
|
+
|
57
|
+
imageNamesUsed = imageNamesUsed(target)
|
58
|
+
images = images(target)
|
59
|
+
|
60
|
+
exit findUnusedImagesHelper(images, imageNamesUsed)
|
61
|
+
end
|
62
|
+
|
63
|
+
no_commands{
|
64
|
+
private def getProject(options)
|
65
|
+
projectPath = options[:project]
|
66
|
+
|
67
|
+
if projectPath.nil?
|
68
|
+
projectPath = ENV["PROJECT_FILE_PATH"]
|
69
|
+
end
|
70
|
+
|
71
|
+
if projectPath.nil?
|
72
|
+
projectPath = Dir.entries('.').select { |f| f.end_with?(".xcodeproj") }.first
|
73
|
+
end
|
74
|
+
|
75
|
+
if projectPath.nil?
|
76
|
+
fail "no xcodeproject found"
|
77
|
+
end
|
78
|
+
|
79
|
+
project = Xcodeproj::Project.open(projectPath)
|
80
|
+
|
81
|
+
project
|
82
|
+
end
|
83
|
+
|
84
|
+
private def getTarget(options, project)
|
85
|
+
targetName = options[:target]
|
86
|
+
|
87
|
+
if targetName.nil?
|
88
|
+
targetName = ENV["TARGETNAME"]
|
89
|
+
end
|
90
|
+
|
91
|
+
if targetName.nil?
|
92
|
+
targetName = project.targets.first.name
|
93
|
+
end
|
94
|
+
|
95
|
+
if targetName.nil?
|
96
|
+
fail "no target found"
|
97
|
+
end
|
98
|
+
|
99
|
+
target = project.targets.select { |target| target.name.eql? targetName }.first
|
100
|
+
|
101
|
+
if target.nil?
|
102
|
+
fail 'no target'
|
103
|
+
end
|
104
|
+
|
105
|
+
target
|
106
|
+
end
|
107
|
+
|
108
|
+
private def codeFiles(target)
|
109
|
+
|
110
|
+
codeFiles = target.source_build_phase.files.to_a.map do |pbx_build_file|
|
111
|
+
pbx_build_file.file_ref.real_path.to_s
|
112
|
+
end.select do |path|
|
113
|
+
path.end_with?(".m", ".mm", ".swift")
|
114
|
+
end.select do |path|
|
115
|
+
File.exists?(path)
|
116
|
+
end
|
117
|
+
|
118
|
+
codeFiles
|
119
|
+
end
|
120
|
+
|
121
|
+
private def assetFiles(target)
|
122
|
+
resources(target, ".xcassets")
|
123
|
+
end
|
124
|
+
|
125
|
+
private def stringsFiles(target)
|
126
|
+
resources(target, ".strings")
|
127
|
+
end
|
128
|
+
|
129
|
+
private def resources(target, ending)
|
130
|
+
target.resources_build_phase.files.to_a.map do |pbx_build_file|
|
131
|
+
pbx_build_file.file_ref.real_path.to_s
|
132
|
+
end.select do |path|
|
133
|
+
path.end_with?(ending)
|
134
|
+
end.select do |path|
|
135
|
+
File.exists?(path)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
private def imageNamesUsed(target)
|
140
|
+
imageNamesUsed = codeFiles(target).flat_map do |file|
|
141
|
+
File.readlines(file).to_s.enum_for(:scan, /#imageLiteral\(resourceName: \\"[^"]*\\"\)/).flat_map {Regexp.last_match}.flat_map do |string|
|
142
|
+
string.to_s.sub!('#imageLiteral(resourceName: \\"','').sub!('\")','')
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
imageNamesUsed
|
147
|
+
end
|
148
|
+
|
149
|
+
private def images(target)
|
150
|
+
|
151
|
+
imageNames = assetFiles(target).flat_map do |assetFile|
|
152
|
+
Dir.entries(assetFile).select do |file|
|
153
|
+
file.end_with?(".imageset")
|
154
|
+
end.map do |file|
|
155
|
+
File.basename(file,File.extname(file))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
imageNames
|
160
|
+
end
|
161
|
+
|
162
|
+
private def findUnusedImagesHelper(images, imageNamesUsed)
|
163
|
+
exitcode = 0
|
164
|
+
|
165
|
+
images.each do |image|
|
166
|
+
if not imageNamesUsed.include? image
|
167
|
+
puts ":: warning: Xclinter findUnusedImages: \"#{image}\" is not used in any imageLiteral and might be obsolete"
|
168
|
+
exitcode = 1
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
return exitcode
|
173
|
+
end
|
174
|
+
|
175
|
+
private def lintImageLiteralsHelper(images, imageNamesUsed)
|
176
|
+
exitcode = 0
|
177
|
+
|
178
|
+
imageNamesUsed.each do |imageNameUsed|
|
179
|
+
if not images.include? imageNameUsed
|
180
|
+
puts ":: error: Xclinter lintImageLiteral: \"#{imageNameUsed}\" does not exist in asset files"
|
181
|
+
exitcode = 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
return exitcode
|
186
|
+
end
|
187
|
+
|
188
|
+
private def lintStringFilesHelper(stringFiles)
|
189
|
+
exitcode = 0
|
190
|
+
|
191
|
+
stringFiles.each do |path|
|
192
|
+
File.foreach(path).with_index do |line, line_num|
|
193
|
+
if not line.strip.empty? and not line.strip.end_with?(";") and not (line.strip.start_with?("/*") and line.strip.end_with?("*/"))
|
194
|
+
puts "#{path}:#{line_num+1}: error: Xclinter lintStringFiles: semicolon missing"
|
195
|
+
exitcode = 1
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
return exitcode
|
201
|
+
end
|
202
|
+
}
|
203
|
+
end
|
204
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xclinter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wolfgang Lutz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.20.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.20.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: xcodeproj
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.16'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.16'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.0'
|
83
|
+
description: xclinter lints various possible problems of xcodeprojects, e.g. broken
|
84
|
+
strings files, unavailable images or unused images.
|
85
|
+
email:
|
86
|
+
- wlut@num42.de
|
87
|
+
executables:
|
88
|
+
- console
|
89
|
+
- setup
|
90
|
+
- xclinter
|
91
|
+
extensions: []
|
92
|
+
extra_rdoc_files: []
|
93
|
+
files:
|
94
|
+
- "./lib/xclinter.rb"
|
95
|
+
- "./lib/xclinter/version.rb"
|
96
|
+
- bin/console
|
97
|
+
- bin/setup
|
98
|
+
- bin/xclinter
|
99
|
+
homepage: https://github.com/num42/xclinter-ruby
|
100
|
+
licenses:
|
101
|
+
- MIT
|
102
|
+
metadata: {}
|
103
|
+
post_install_message:
|
104
|
+
rdoc_options: []
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
requirements: []
|
118
|
+
rubyforge_project:
|
119
|
+
rubygems_version: 2.5.2.1
|
120
|
+
signing_key:
|
121
|
+
specification_version: 4
|
122
|
+
summary: xclinter lints various possible problems of xcodeprojects
|
123
|
+
test_files: []
|