1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
# frozen_string_literal: true
module IpynbDiff
require 'oj'
# Creates a map from a symbol to the line number it appears in a Json file
#
# Example:
#
# Input:
#
# 1. {
# 2. 'obj1': [
# 3. {
# 4. 'obj2': 5
# 5. },
# 6. 3,
# 7. {
# 8. 'obj3': {
# 9. 'obj4': 'b'
# 10. }
# 11. }
# 12. ]
# 13.}
#
# Output:
#
# Symbol Line Number
# .obj1 -> 2
# .obj1.0 -> 3
# .obj1.0 -> 3
# .obj1.0.obj2 -> 4
# .obj1.1 -> 6
# .obj1.2 -> 7
# .obj1.2.obj3 -> 8
# .obj1.2.obj3.obj4 -> 9
#
class SymbolMap
# rubocop:disable Lint/UnusedMethodArgument
class << self
def handler
@handler ||= SymbolMap.new
end
def parser
@parser ||= Oj::Parser.new(:saj).tap { |p| p.handler = handler }
end
def parse(notebook, *args)
handler.reset
parser.parse(notebook)
handler.symbols
end
end
attr_accessor :symbols
def hash_start(key, line, column)
add_symbol(key_or_index(key), line)
end
def hash_end(key, line, column)
@current_path.pop
end
def array_start(key, line, column)
@current_array_index << 0
add_symbol(key, line)
end
def array_end(key, line, column)
@current_path.pop
@current_array_index.pop
end
def add_value(value, key, line, column)
add_symbol(key_or_index(key), line)
@current_path.pop
end
def add_symbol(symbol, line)
@symbols[@current_path.append(symbol).join('.')] = line if symbol
end
def key_or_index(key)
if key.nil? # value in an array
if @current_path.empty?
@current_path = ['']
return
end
symbol = @current_array_index.last
@current_array_index[-1] += 1
symbol
else
key
end
end
def reset
@current_path = []
@symbols = {}
@current_array_index = []
end
# rubocop:enable Lint/UnusedMethodArgument
end
end
|