Skip to content

Instantly share code, notes, and snippets.

@munckymagik
Created August 30, 2019 21:32
Show Gist options
  • Save munckymagik/19eda6561dc8c22e38db34641387971c to your computer and use it in GitHub Desktop.
Save munckymagik/19eda6561dc8c22e38db34641387971c to your computer and use it in GitHub Desktop.
A Julia script that analyses interface differences between a bunch of Ruby presenter files
using CSV, DataFrames, Query
struct Record
class_name::String
public::Bool
item_type::String
item_name::String
end
function parse_file(file_name::String)::Array{Record}
elems = Record[]
class_name::Union{Nothing, String} = nothing
public = true
# for each line
for line in eachline(file_name)
# skip blanks
if length(line) == 0
continue
end
if occursin("private", line)
public = false
continue
end
# if class name memo it
m = match(r"class (?<class_name>\w+)", line)
if m !== nothing
class_name = m[:class_name]
continue
end
# if constant push it's name
m = match(r"(?<const_name>[A-Z_]+)\s+=", line)
if m !== nothing
push!(elems, Record(class_name, public, "const", m[:const_name]))
continue
end
# if function push it's signature
m = match(r"^\s+def +(?<def_sig>[^#]+)", line)
if m !== nothing
push!(elems, Record(class_name, public, "def", rstrip(m[:def_sig])))
continue
end
# if attr_reader push it's args
m = match(r"^\s+attr_reader +(?<attrs>.*)", line)
if m !== nothing
symbols = split(rstrip(m[:attrs]), ", ")
attrs = map(s -> s[2:end], symbols) # stripe the leading colon
recs = map(s -> Record(class_name, public, "attr", s), attrs)
append!(elems, recs)
continue
end
end
elems
end
function parse_files()
elems = Record[]
# iteratate over files and open to read lines
for file_name in file_names(r"^\w\w_presenter")
append!(elems, parse_file(file_name))
end
elems
end
parse_files_async() = asyncmap(parse_file, file_names(r"^\w\w_presenter")) |> flatten
function show_stats(data::Array{Record})
result = @from i in data begin
@group i by i.item_name into g
@select {Name=key(g), Count=length(g)}
@collect DataFrame
end
sort!(result, [order(:Count, rev=true), :Name])
println(result)
end
# List files filter for presenters
file_names(pattern) = filter((fn) -> occursin(pattern, fn), readdir())
# Flatten and collect an iterable into an array
flatten = collect ∘ Iterators.flatten
# Write the records out to a CSV file.
write_csv(file, records) = CSV.write(file, records; writeheader=true)
function main()
elems = parse_files_async()
show_stats(elems)
end
if abspath(PROGRAM_FILE) == @__FILE__
main()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment