Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script that takes a ObjC .m file and tries to find unused (or duplicate) import statements by commenting out each #import line in turn and seeing if the project still compiles. You will have to change BUILD_DIR & BUILD_CMD.
#!/usr/bin/env ruby -w
class String
def starts_with?(prefix)
prefix.respond_to?(:to_str) && self[0, prefix.length] == prefix
end
end
HEADER_REGEX = /^#import\s+["<](.*)[">]/
BUILD_DIR = File.expand_path("~/Code/project_xyz")
BUILD_CMD = 'xcodebuild -target "Project XYZ" -configuration "Debug" build > /tmp/import_minimizer-build.log 2>&1'
FILE_TO_MINIMIZE = ARGV.shift
unless File.readable?(FILE_TO_MINIMIZE)
puts "Usage: import_minimizer.rb FileToMinimize.m"
puts "\t file path must be relative to #{BUILD_DIR} (or an absolute path)"
exit 1
end
Dir.chdir(BUILD_DIR)
lines = open(FILE_TO_MINIMIZE, "r").each_line.to_a
line_no = 0
counter = 0
puts "testing #{FILE_TO_MINIMIZE}"
printf ". checking for duplicates"
seen_headers = []
while line_no < lines.length
line = lines[line_no]
line_no += 1
next unless line.starts_with? "#import "
header = line[HEADER_REGEX, 1]
if seen_headers.include?(header)
lines[line_no-1] = "// #{line.strip} // -- duplicate\n"
counter += 1
end
seen_headers << header
end
puts " - found: #{counter}"
line_no = 0
while line_no < lines.length
line = lines[line_no]
unless line.starts_with? "#import "
line_no += 1
next
end
orig_line = line
header = line[HEADER_REGEX, 1]
printf ". checking import: #{header}"
lines[line_no] = "// #{orig_line.strip} // -- not needed\n"
open(FILE_TO_MINIMIZE, "w+") { |f| f.write(lines.join) }
`#{BUILD_CMD}`
if ($?.exitstatus != 0)
lines[line_no] = orig_line
puts " - needed"
else
puts " - NOT needed"
counter += 1
end
line_no += 1
end
puts "\nFound #{counter} #import's that are not needed / duplicates"
open(FILE_TO_MINIMIZE, "w+") { |f| f.write(lines.join) }
@soniccat

This comment has been minimized.

Show comment
Hide comment
@soniccat

soniccat Feb 16, 2016

recommend to add ARGV.each do|file| to be able to use it this way
find . -name "*.[mh]" | xargs ruby ./import_minimizer.rb

soniccat commented Feb 16, 2016

recommend to add ARGV.each do|file| to be able to use it this way
find . -name "*.[mh]" | xargs ruby ./import_minimizer.rb

@gbattiston

This comment has been minimized.

Show comment
Hide comment
@gbattiston

gbattiston Jul 27, 2017

Hi, I just have a question on how exactly to use this script, because I keep getting this error.

import_minimizer.rb:16:in readable?': no implicit conversion of nil into String (TypeError) from import_minimizer.rb:16:in

'

I changed BUILD_DIR & BUILD_CMD correctly but I can't get this to work.

Thanks!!

gbattiston commented Jul 27, 2017

Hi, I just have a question on how exactly to use this script, because I keep getting this error.

import_minimizer.rb:16:in readable?': no implicit conversion of nil into String (TypeError) from import_minimizer.rb:16:in

'

I changed BUILD_DIR & BUILD_CMD correctly but I can't get this to work.

Thanks!!

@gbattiston

This comment has been minimized.

Show comment
Hide comment
@gbattiston

gbattiston Jul 27, 2017

@soniccat I got it to work, but It only checks the first file with your way.

Is there a way to recursively search every folder and check every file?

gbattiston commented Jul 27, 2017

@soniccat I got it to work, but It only checks the first file with your way.

Is there a way to recursively search every folder and check every file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment