Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark unused code #147

Merged
merged 3 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 24 additions & 4 deletions loafwallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -3772,6 +3772,7 @@
buildPhases = (
825805FFD443BACDA18265D0 /* [CP] Check Pods Manifest.lock */,
2430679A238F538C00EBEA99 /* Update Localizable using BartyCrouch */,
58A9FE4829191E4700B75825 /* Check for unused code */,
75A2A78C1DA5934300A983D8 /* Sources */,
75A2A78D1DA5934300A983D8 /* Frameworks */,
75A2A78E1DA5934300A983D8 /* Resources */,
Expand Down Expand Up @@ -4026,6 +4027,25 @@
shellPath = /bin/sh;
shellScript = "## This only notates strings that have yet to be localized. The Base Localizable file is wnere the change needs to be changed.\n\nif which bartycrouch > /dev/null; then\n bartycrouch update -x\n bartycrouch lint -x\nelse\n echo \"warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch\"\nfi\n";
};
58A9FE4829191E4700B75825 /* Check for unused code */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Check for unused code";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "file=\"unused.rb\"\nif [ -f \"$file\" ]\nthen\necho \"$file found.\"\nruby unused.rb xcode\nelse\necho \"unused.rb doesn't exist\"\nfi\n";
};
825805FFD443BACDA18265D0 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
Expand Down Expand Up @@ -4819,7 +4839,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = loafwallet/loafwallet.entitlements;
CURRENT_PROJECT_VERSION = 401;
CURRENT_PROJECT_VERSION = 406;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ZV7987N2ZC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
Expand Down Expand Up @@ -5239,7 +5259,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = loafwallet/loafwallet.entitlements;
CURRENT_PROJECT_VERSION = 401;
CURRENT_PROJECT_VERSION = 406;
DEVELOPMENT_TEAM = ZV7987N2ZC;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;
FRAMEWORK_SEARCH_PATHS = (
Expand Down Expand Up @@ -5371,7 +5391,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = loafwallet/loafwallet.entitlements;
CURRENT_PROJECT_VERSION = 401;
CURRENT_PROJECT_VERSION = 406;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ZV7987N2ZC;
FRAMEWORK_SEARCH_PATHS = (
Expand Down
2 changes: 2 additions & 0 deletions loafwallet/PartnerData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ struct Partner {
let bitrefill = Partner(logo: UIImage(named: "bitrefillLogo")!, headerTitle: S.BuyCenter.Cells.bitrefillTitle, details: S.BuyCenter.Cells.bitrefillFinancialDetails)
let moonpay = Partner(logo: UIImage(named: "moonpay-logo")!, headerTitle: S.BuyCenter.Cells.moonpayTitle, details: S.BuyCenter.Cells.moonpayFinancialDetails)
let simplex = Partner(logo: UIImage(named: "simplexLogo")!, headerTitle: S.BuyCenter.Cells.simplexTitle, details: S.BuyCenter.Cells.simplexFinancialDetails)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tx

return [bitrefill, moonpay, simplex]
}
}

229 changes: 229 additions & 0 deletions unused.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
#!/usr/bin/ruby
#encoding: utf-8
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

class Item
def initialize(file, line, at)
@file = file
@line = line
@at = at + 1
if match = line.match(/(func|let|var|class|enum|struct|protocol)\s+(\w+)/)
@type = match.captures[0]
@name = match.captures[1]
end
end

def modifiers
return @modifiers if @modifiers
@modifiers = []
if match = @line.match(/(.*?)#{@type}/)
@modifiers = match.captures[0].split(" ")
end
return @modifiers
end

def name
@name
end

def file
@file
end

def to_s
serialize
end
def to_str
serialize
end

def full_file_path
Dir.pwd + '/' + @file
end

def serialize
"Item< #{@type.to_s.green} #{@name.to_s.yellow} [#{modifiers.join(" ").cyan}] from: #{@file}:#{@at}:0>"
end

def to_xcode
"#{full_file_path}:#{@at}:0: warning: #{@type.to_s} #{@name.to_s} is unused"
end


end
class Unused
def find
items = []
all_files = Dir.glob("**/*.swift").reject do |path|
File.directory?(path)
end

all_files.each { |my_text_file|
file_items = grab_items(my_text_file)
file_items = filter_items(file_items)

non_private_items, private_items = file_items.partition { |f| !f.modifiers.include?("private") && !f.modifiers.include?("fileprivate") }
items += non_private_items

# Usage within the file
if private_items.length > 0
find_usages_in_files([my_text_file], [], private_items)
end

}

puts "Total items to be checked #{items.length}"

items = items.uniq { |f| f.name }
puts "Total unique items to be checked #{items.length}"

puts "Starting searching globally it can take a while".green

xibs = Dir.glob("**/*.xib")
storyboards = Dir.glob("**/*.storyboard")

find_usages_in_files(all_files, xibs + storyboards, items)

end

def ignore_files_with_regexps(files, regexps)
files.select { |f| regexps.all? { |r| Regexp.new(r).match(f.file).nil? } }
end

def ignoring_regexps_from_command_line_args
regexps = []
should_skip_predefined_ignores = false

arguments = ARGV.clone
until arguments.empty?
item = arguments.shift
if item == "--ignore"
regex = arguments.shift
regexps += [regex]
end

if item == "--skip-predefined-ignores"
should_skip_predefined_ignores = true
end
end

if not should_skip_predefined_ignores
regexps += [
"^Pods/",
"fastlane/",
"Tests.swift$",
"Spec.swift$",
"Tests/"
]
end

regexps
end

def find_usages_in_files(files, xibs, items_in)
items = items_in
usages = items.map { |f| 0 }
files.each { |file|
lines = File.readlines(file).map {|line| line.gsub(/^[^\/]*\/\/.*/, "") }
words = lines.join("\n").split(/\W+/)
words_arrray = words.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten

wf = Hash[*words_arrray]

items.each_with_index { |f, i|
usages[i] += (wf[f.name] || 0)
}
# Remove all items which has usage 2+
indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i }

# reduce usage array if we found some functions already
indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) }
}

xibs.each { |xib|
lines = File.readlines(xib).map {|line| line.gsub(/^\s*\/\/.*/, "") }
full_xml = lines.join(" ")
classes = full_xml.scan(/(class|customClass)="([^"]+)"/).map { |cd| cd[1] }
classes_array = classes.group_by { |w| w }.map { |w, ws| [w, ws.length] }.flatten

wf = Hash[*classes_array]

items.each_with_index { |f, i|
usages[i] += (wf[f.name] || 0)
}
# Remove all items which has usage 2+
indexes = usages.each_with_index.select { |u, i| u >= 2 }.map { |f, i| i }

# reduce usage array if we found some functions already
indexes.reverse.each { |i| usages.delete_at(i) && items.delete_at(i) }

}

regexps = ignoring_regexps_from_command_line_args()

items = ignore_files_with_regexps(items, regexps)

if items.length > 0
if ARGV[0] == "xcode"
$stderr.puts "#{items.map { |e| e.to_xcode }.join("\n")}"
else
puts "#{items.map { |e| e.to_s }.join("\n ")}"
end
end
end

def grab_items(file)
lines = File.readlines(file).map {|line| line.gsub(/^\s*\/\/.*/, "") }
items = lines.each_with_index.select { |line, i| line[/(func|let|var|class|enum|struct|protocol)\s+\w+/] }.map { |line, i| Item.new(file, line, i)}
end

def filter_items(items)
customFilterNames = [
"applicationDidBecomeActive",
"applicationWillEnterForeground",
"applicationDidEnterBackground",
"applicationWillResignActive",
"textViewDidBeginEditing",
"textViewShouldEndEditing",
"textViewDidEndEditing",
"mailComposeController",
"messageComposeViewController",
"gestureRecognizerShouldBegin",
"metadataOutput"
]
items.select { |f|
!f.name.start_with?("test") && !f.modifiers.include?("@IBAction") && !f.modifiers.include?("override") && !f.modifiers.include?("@objc") && !f.modifiers.include?("@IBInspectable") && !f.name.include?("_Previews") && !customFilterNames.include?(f.name)
}
end

end

class String
def black; "\e[30m#{self}\e[0m" end
def red; "\e[31m#{self}\e[0m" end
def green; "\e[32m#{self}\e[0m" end
def yellow; "\e[33m#{self}\e[0m" end
def blue; "\e[34m#{self}\e[0m" end
def magenta; "\e[35m#{self}\e[0m" end
def cyan; "\e[36m#{self}\e[0m" end
def gray; "\e[37m#{self}\e[0m" end

def bg_black; "\e[40m#{self}\e[0m" end
def bg_red; "\e[41m#{self}\e[0m" end
def bg_green; "\e[42m#{self}\e[0m" end
def bg_brown; "\e[43m#{self}\e[0m" end
def bg_blue; "\e[44m#{self}\e[0m" end
def bg_magenta; "\e[45m#{self}\e[0m" end
def bg_cyan; "\e[46m#{self}\e[0m" end
def bg_gray; "\e[47m#{self}\e[0m" end

def bold; "\e[1m#{self}\e[22m" end
def italic; "\e[3m#{self}\e[23m" end
def underline; "\e[4m#{self}\e[24m" end
def blink; "\e[5m#{self}\e[25m" end
def reverse_color; "\e[7m#{self}\e[27m" end
end


Unused.new.find