diff options
Diffstat (limited to 'gems/ipynbdiff/lib/ipynb_diff/symbol_map.rb')
-rw-r--r-- | gems/ipynbdiff/lib/ipynb_diff/symbol_map.rb | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/gems/ipynbdiff/lib/ipynb_diff/symbol_map.rb b/gems/ipynbdiff/lib/ipynb_diff/symbol_map.rb new file mode 100644 index 00000000000..383f1de5c18 --- /dev/null +++ b/gems/ipynbdiff/lib/ipynb_diff/symbol_map.rb @@ -0,0 +1,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 |