Skip to content

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.

Copy link

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.

Copy link

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.

Copy link

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
You can’t perform that action at this time.