epuber 0.9.4 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,7 +21,7 @@ module Epuber
21
21
  end
22
22
 
23
23
  def run
24
- UI.puts "📖 Loading EPUB file #{@filepath}"
24
+ UI.info "📖 Loading EPUB file #{@filepath}"
25
25
 
26
26
  Zip::File.open(@filepath) do |zip_file|
27
27
  @zip_file = zip_file
@@ -29,22 +29,22 @@ module Epuber
29
29
  validate_mimetype
30
30
 
31
31
  @opf_path = content_opf_path
32
- UI.puts " Parsing OPF file at #{@opf_path}"
32
+ UI.info " Parsing OPF file at #{@opf_path}"
33
33
  @opf = OpfFile.new(zip_file.read(@opf_path))
34
34
 
35
35
  if zip_file.find_entry(ENCRYPTION_PATH)
36
- UI.puts ' Parsing encryption.xml file'
36
+ UI.info ' Parsing encryption.xml file'
37
37
  @encryption_handler = EncryptionHandler.new(zip_file.read(ENCRYPTION_PATH), @opf)
38
38
  end
39
39
 
40
- UI.puts ' Generating bookspec file'
40
+ UI.info ' Generating bookspec file'
41
41
  basename = File.basename(@filepath, File.extname(@filepath))
42
42
  File.write("#{basename}.bookspec", generate_bookspec)
43
43
 
44
44
  export_files
45
45
 
46
- UI.puts '' # empty line
47
- UI.puts <<~TEXT.rstrip.ansi.green
46
+ UI.info '' # empty line
47
+ UI.info <<~TEXT.rstrip.ansi.green
48
48
  🎉 Project initialized.
49
49
  Please review generated #{basename}.bookspec file and start using Epuber.
50
50
 
@@ -112,13 +112,13 @@ module Epuber
112
112
  extension = File.extname(item.href).downcase
113
113
  if text_file_extensions.include?(extension) &&
114
114
  @opf.spine_items.none? { |spine_item| spine_item.idref == item.id }
115
- UI.puts " Skipping #{item.href} (not in spine)"
115
+ UI.info " Skipping #{item.href} (not in spine)"
116
116
  next
117
117
  end
118
118
 
119
119
  # ignore ncx file
120
120
  if item.media_type == 'application/x-dtbncx+xml'
121
- UI.puts " Skipping #{item.href} (ncx file)"
121
+ UI.info " Skipping #{item.href} (ncx file)"
122
122
  next
123
123
  end
124
124
 
@@ -127,7 +127,7 @@ module Epuber
127
127
  .join(item.href)
128
128
  .to_s
129
129
 
130
- UI.puts " Exporting #{item.href} (from #{full_path})"
130
+ UI.info " Exporting #{item.href} (from #{full_path})"
131
131
 
132
132
  contents = @zip_file.read(full_path)
133
133
  contents = @encryption_handler.process_file(full_path, contents) if @encryption_handler
data/lib/epuber/plugin.rb CHANGED
@@ -12,7 +12,7 @@ module Epuber
12
12
  #
13
13
  attr_reader :instances
14
14
 
15
- # @param [String] file_path path to plugin file
15
+ # @param [String] relative_path path to plugin file (relative to project root)
16
16
  #
17
17
  def initialize(file_path)
18
18
  super(file_path)
data/lib/epuber/server.rb CHANGED
@@ -116,7 +116,7 @@ module Epuber
116
116
 
117
117
  super() do |server|
118
118
  $stderr = old_stderr
119
- UI.puts "Started development server on #{server.host}:#{server.port}"
119
+ UI.info "Started development server on #{server.host}:#{server.port}"
120
120
 
121
121
  host = if server.host == '0.0.0.0'
122
122
  'localhost'
@@ -187,13 +187,13 @@ module Epuber
187
187
  def self._log(level, message)
188
188
  case level
189
189
  when :ui
190
- UI.puts message
190
+ UI.info message
191
191
  when :info
192
- UI.puts "INFO: #{message}" if verbose
192
+ UI.info "INFO: #{message}" if verbose
193
193
  when :get
194
- UI.puts " GET: #{message}" if verbose
194
+ UI.info " GET: #{message}" if verbose
195
195
  when :ws
196
- UI.puts " WS: #{message}" if verbose
196
+ UI.info " WS: #{message}" if verbose
197
197
  else
198
198
  raise "Unknown log level #{level}"
199
199
  end
@@ -29,21 +29,27 @@ module Epuber
29
29
  # Find file in source or destination paths
30
30
  #
31
31
  # @param [String] pattern
32
+ # @param [String] context_path path to directory that is used as context for finding
33
+ # @param [Array<Symbol>, Symbol] groups
32
34
  # @param [Thread::Backtrace::Location] location
33
35
  #
34
36
  # @return [Epuber::Compiler::FileTypes::AbstractFile, nil]
35
37
  #
36
- def find_file(pattern, location: caller_locations.first)
38
+ def find_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
37
39
  return pattern if pattern.is_a?(Compiler::FileTypes::AbstractFile)
38
40
 
39
41
  UI.error!("Pattern for finding file can't be nil", location: location) if pattern.nil?
40
42
 
41
43
  begin
42
- path = @compilation_context.file_resolver.source_finder.find_file(pattern)
44
+ path = @compilation_context.file_resolver.source_finder.find_file(pattern, context_path: context_path,
45
+ groups: groups)
46
+ path = File.join(context_path, path) if context_path
43
47
  @compilation_context.file_resolver.file_with_source_path(path)
44
48
  rescue Compiler::FileFinders::FileNotFoundError
45
49
  begin
46
- path = @compilation_context.file_resolver.dest_finder.find_file(pattern)
50
+ path = @compilation_context.file_resolver.dest_finder.find_file(pattern, context_path: context_path,
51
+ groups: groups)
52
+ path = File.join(context_path, path) if context_path
47
53
  @compilation_context.file_resolver.file_with_destination_path(path)
48
54
  rescue Compiler::FileFinders::FileNotFoundError
49
55
  nil
@@ -54,27 +60,35 @@ module Epuber
54
60
  # Find files destination paths
55
61
  #
56
62
  # @param [String] pattern
63
+ # @param [String] context_path path to directory that is used as context for finding
64
+ # @param [Array<Symbol>, Symbol] groups
57
65
  # @param [Thread::Backtrace::Location] location
58
66
  #
59
67
  # @return [Array<Epuber::Compiler::FileTypes::AbstractFile>]
60
68
  #
61
- def find_destination_files(pattern, location: caller_locations.first)
69
+ def find_destination_files(pattern, context_path: nil, groups: nil, location: caller_locations.first)
62
70
  UI.error!("Pattern for finding file can't be nil", location: location) if pattern.nil?
63
71
 
64
- paths = @compilation_context.file_resolver.dest_finder.find_files(pattern)
72
+ paths = @compilation_context.file_resolver.dest_finder.find_files(pattern, context_path: context_path,
73
+ groups: groups)
65
74
  paths.map { |path| @compilation_context.file_resolver.file_with_destination_path(path) }
66
75
  end
67
76
 
68
77
  # Find file and raise exception if not found
69
78
  #
70
79
  # @param [String] pattern
80
+ # @param [String] context_path path to directory that is used as context for finding
81
+ # @param [Array<Symbol>, Symbol] groups
71
82
  # @param [Thread::Backtrace::Location] location
72
83
  #
73
84
  # @return [Epuber::Compiler::FileTypes::AbstractFile]
74
85
  #
75
- def get_file(pattern, location: caller_locations.first)
76
- file = find_file(pattern, location: location)
77
- UI.error!("File with pattern #{pattern} not found", location: location) unless file
86
+ def get_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
87
+ file = find_file(pattern, context_path: context_path, groups: groups, location: location)
88
+ unless file
89
+ UI.error!("File with pattern #{pattern} not found (context path: #{context_path || 'nil'})",
90
+ location: location)
91
+ end
78
92
 
79
93
  file
80
94
  end
@@ -82,12 +96,14 @@ module Epuber
82
96
  # Read file from destination path (raises exception if not found)
83
97
  #
84
98
  # @param [String] pattern
99
+ # @param [String] context_path path to directory that is used as context for finding
100
+ # @param [Array<Symbol>, Symbol] groups
85
101
  # @param [Thread::Backtrace::Location] location
86
102
  #
87
103
  # @return [String]
88
104
  #
89
- def read_destination_file(pattern, location: caller_locations.first)
90
- file = get_file(pattern, location: location)
105
+ def read_destination_file(pattern, context_path: nil, groups: nil, location: caller_locations.first)
106
+ file = get_file(pattern, context_path: context_path, groups: groups, location: location)
91
107
  File.read(file.final_destination_path)
92
108
  end
93
109
 
@@ -95,12 +111,14 @@ module Epuber
95
111
  #
96
112
  # @param [String] pattern
97
113
  # @param [String] content
114
+ # @param [String] context_path path to directory that is used as context for finding
115
+ # @param [Array<Symbol>, Symbol] groups
98
116
  # @param [Thread::Backtrace::Location] location
99
117
  #
100
118
  # @return [void]
101
119
  #
102
- def write_destination_file(pattern, content, location: caller_locations.first)
103
- file = get_file(pattern, location: location)
120
+ def write_destination_file(pattern, content, context_path: nil, groups: nil, location: caller_locations.first)
121
+ file = get_file(pattern, context_path: context_path, groups: groups, location: location)
104
122
  Compiler::FileTypes::AbstractFile.write_to_file(content, file.final_destination_path)
105
123
  end
106
124
  end
@@ -1,235 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/object/try'
4
- require 'nokogiri'
3
+ require 'delegate'
5
4
 
6
- require_relative 'ruby_extensions/thread'
7
- require_relative 'command'
5
+ require_relative 'utils/logger/console_logger'
8
6
 
9
7
  module Epuber
10
- class UserInterface
11
- Location = Struct.new(:path, :lineno, :column, keyword_init: true)
12
-
13
- class << self
14
- # @return [Epuber::Command]
15
- #
16
- attr_accessor :current_command
17
- end
18
-
19
- # Fatal error, prints message and exit with return code 1
20
- #
21
- # @param [Exception, String] message message of the error
22
- # @param [Thread::Backtrace::Location] location location of the error
23
- #
24
- def self.error!(message, location: nil)
25
- error(message, location: location)
26
- exit(1)
27
- end
28
-
29
- # Fatal error, prints message and exit with return code 1
30
- #
31
- # @param [String] message message of the error
32
- # @param [Thread::Backtrace::Location] location location of the error
33
- # @param [Bool] backtrace output backtrace locations, nil == automatic, true == always and false == never
34
- #
35
- def self.error(message, location: nil)
36
- _clear_processing_line_for_new_output do
37
- $stdout.puts(_format_message(:error, message, location: location))
38
- if current_command&.verbose?
39
- _print_backtrace(location.try(:backtrace_locations) || message.try(:backtrace_locations) || caller_locations,
40
- location: location)
41
- end
42
- end
43
- end
44
-
45
- # @param [String] message message of the error
46
- # @param [Thread::Backtrace::Location] location location of the error
47
- #
48
- def self.warning(message, location: nil)
49
- _clear_processing_line_for_new_output do
50
- $stdout.puts(_format_message(:warning, message, location: location))
51
- end
52
- end
53
-
54
- # @param [#to_s] problem some problem, object just have to know to convert self into string with method #to_s
55
- #
56
- def self.print_processing_problem(problem)
57
- _clear_processing_line_for_new_output do
58
- $stdout.puts(problem.to_s.ansi.send(_color_from_level(:warning)))
59
- end
60
- end
61
-
62
- # @param [String] info_text
63
- #
64
- def self.print_processing_debug_info(info_text)
65
- return unless current_command&.verbose?
66
-
67
- _clear_processing_line_for_new_output do
68
- message = if @current_file.nil?
69
- "▸ #{info_text}"
70
- else
71
- "▸ #{@current_file.source_path}: #{info_text}"
72
- end
73
-
74
- $stdout.puts(message.ansi.send(_color_from_level(:debug)))
75
- end
76
- end
77
-
78
- # @param [Compiler::FileTypes::AbstractFile] file
79
- #
80
- # @return nil
81
- #
82
- def self.print_processing_file(file, index, count)
83
- remove_processing_file_line
84
-
85
- @current_file = file
86
-
87
- @last_processing_file_line = "▸ Processing #{file.source_path} (#{index + 1} of #{count})"
88
- $stdout.print(@last_processing_file_line)
89
- end
90
-
91
- def self.remove_processing_file_line
92
- last_line = @last_processing_file_line
93
-
94
- unless @last_processing_file_line.nil?
95
- $stdout.print("\033[2K") # remove line, but without moving cursor
96
- $stdout.print("\r") # go to beginning of line
97
- @last_processing_file_line = nil
98
- end
99
-
100
- last_line
101
- end
102
-
103
- def self.processing_files_done
104
- remove_processing_file_line
105
-
106
- @current_file = nil
107
- end
108
-
109
- def self.puts(message)
110
- _clear_processing_line_for_new_output do
111
- $stdout.puts(message)
112
- end
113
- end
114
-
115
- # @param [Compiler::FileTypes::AbstractFile] file
116
- # @param [String] step_name
117
- # @param [Fixnum] time
8
+ class UserInterface < Delegator
9
+ # @return [Logger::AbstractLogger]
118
10
  #
119
- def self.print_step_processing_time(step_name, time = nil)
120
- return yield if !current_command || !current_command.debug_steps_times
121
-
122
- remove_processing_file_line
11
+ attr_reader :logger
123
12
 
124
- if block_given?
125
- start = Time.now
126
- returned_value = yield
13
+ def initialize
14
+ super(nil)
127
15
 
128
- time = Time.now - start
129
- end
130
-
131
- info_text = "Step #{step_name} took #{time * 1000} ms"
132
- message = if @current_file.nil?
133
- "▸ #{info_text}"
134
- else
135
- "▸ #{@current_file.source_path}: #{info_text}"
136
- end
137
-
138
- $stdout.puts(_format_message(:debug, message))
139
-
140
- returned_value
16
+ @logger = Logger::ConsoleLogger.new
141
17
  end
142
18
 
143
- def self._clear_processing_line_for_new_output
144
- last_line = remove_processing_file_line
145
-
146
- yield
147
-
148
- @last_processing_file_line = last_line
149
- $stdout.print(last_line)
150
- end
151
-
152
- # @param [Symbol] level color of the output
153
- #
154
- # @return [Symbol] color
155
- #
156
- def self._color_from_level(level)
157
- case level
158
- when :error then :red
159
- when :warning then :yellow
160
- when :normal then :white
161
- when :debug then :blue
162
- else
163
- raise "Unknown output level #{level}"
164
- end
19
+ def __getobj__
20
+ @logger
165
21
  end
166
22
 
167
- # @param [Thread::Backtrace::Location, Nokogiri::XML::Node] obj
168
- #
169
- # @return [Location]
170
- #
171
- def self._location_from_obj(obj)
172
- case obj
173
- when ::Thread::Backtrace::Location
174
- Location.new(path: obj.path, lineno: obj.lineno)
175
- when ::Nokogiri::XML::Node
176
- Location.new(path: obj.document.file_path, lineno: obj.line)
177
- when Location
178
- obj
179
- when Epuber::Compiler::FileTypes::AbstractFile
180
- Location.new(path: obj.source_path)
181
- end
182
- end
183
-
184
- # @param [Symbol] level color of the output
185
- # @param [String] message message of the error
186
- # @param [Thread::Backtrace::Location] location location of the error
187
- #
188
- # @return [String] formatted message
189
- #
190
- def self._format_message(level, message, location: nil)
191
- location = _location_from_obj(location)
192
-
193
- comps = []
194
- comps << message.to_s
195
- message_already_formatted =
196
- message.is_a?(Epuber::Compiler::Problem) || message.is_a?(Epuber::Checker::TextChecker::MatchProblem)
197
-
198
- if !location.nil? && !message_already_formatted
199
- path = location.path
200
-
201
- # calculate relative path when path is absolute and in project
202
- path = path[Config.instance.project_path.size + 1..-1] if path.start_with?(Config.instance.project_path)
203
-
204
- line_parts = [
205
- " (in file #{path}",
206
- ]
207
- line_parts << "line #{location.lineno}" if location.lineno
208
- line_parts << "column #{location.column}" if location.column
209
-
210
- comps << "#{line_parts.join(' ')})"
211
- end
212
-
213
- comps.join("\n").ansi.send(_color_from_level(level))
214
- end
215
-
216
- # @param [Array<Thread::Backtrace::Location>] locations locations of the error (only for verbose output)
217
- # @param [Thread::Backtrace::Location] location location of the error
218
- #
219
- # @return [String] formatted message
220
- #
221
- def self._format_backtrace(locations, location: nil)
222
- index = locations.index(location) || 0
223
- locations[index, locations.size].map(&:to_s)
224
- end
225
-
226
- # @param [Thread::Backtrace::Location] location location of the error
227
- #
228
- def self._print_backtrace(locations, location: nil)
229
- $stdout.puts(_format_backtrace(locations, location: location)) if current_command.verbose?
23
+ def __setobj__(obj)
24
+ @logger = obj
230
25
  end
231
26
  end
232
27
 
233
28
  # shortcut
234
- UI = UserInterface
29
+ UI = UserInterface.new
235
30
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Epuber
4
+ Location = Struct.new(:path, :lineno, :column, keyword_init: true) do
5
+ # !@attribute [r] path
6
+ # @return [String] path to file
7
+
8
+ # !@attribute [r] lineno
9
+ # @return [Integer, nil] line number
10
+
11
+ # !@attribute [r] column
12
+ # @return [Integer, nil] column number
13
+ end
14
+ end
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/try'
4
+ require 'nokogiri'
5
+
6
+ require_relative '../location'
7
+
8
+ module Epuber
9
+ module Logger
10
+ class AbstractLogger
11
+ LEVELS = %i[
12
+ error
13
+ warning
14
+ info
15
+ debug
16
+ ].freeze
17
+
18
+ # @return [Boolean]
19
+ #
20
+ attr_accessor :verbose
21
+
22
+ # @return [Boolean]
23
+ #
24
+ attr_accessor :debug_steps_times
25
+
26
+ # @param [Hash] opts
27
+ # @option opts [Boolean] :verbose (false)
28
+ # @option opts [Boolean] :debug_steps_times (false)
29
+ #
30
+ def initialize(opts = {})
31
+ @verbose = opts.fetch(:verbose, false)
32
+ @debug_steps_times = opts.fetch(:debug_steps_times, false)
33
+
34
+ @current_file = nil
35
+ @sticky_message = nil
36
+ @error_was_logged = false
37
+ end
38
+
39
+ # Report error message
40
+ #
41
+ # @param [String, #to_s] message
42
+ # @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
43
+ # @param [Boolean] stick if true, the error message will be sticked to the previous one
44
+ #
45
+ def error!(message, location: nil, backtrace: caller_locations)
46
+ _common_log(:error, message, location: location, backtrace: backtrace)
47
+ exit(1)
48
+ end
49
+
50
+ # Report error message
51
+ #
52
+ # @param [String, #to_s] message
53
+ # @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
54
+ # @param [Boolean] stick if true, the error message will be sticked to the previous one
55
+ #
56
+ def error(message, sticky: false, location: nil, backtrace: caller_locations)
57
+ _common_log(:error, message, sticky: sticky, location: location, backtrace: backtrace)
58
+ end
59
+
60
+ # Report warning message
61
+ #
62
+ # @param [String, #to_s] message
63
+ # @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
64
+ #
65
+ def warning(message, sticky: false, location: nil, backtrace: caller_locations)
66
+ _common_log(:warning, message, sticky: sticky, location: location, backtrace: backtrace)
67
+ end
68
+
69
+ # Report info message
70
+ #
71
+ # @param [String, #to_s] message
72
+ # @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
73
+ #
74
+ def info(message, sticky: false, location: nil, backtrace: caller_locations)
75
+ _common_log(:info, message, sticky: sticky, location: location, backtrace: backtrace)
76
+ end
77
+
78
+ # Report debug message
79
+ #
80
+ # @param [String, #to_s] message
81
+ # @param [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node, nil] location
82
+ #
83
+ def debug(message, sticky: false, location: nil, backtrace: caller_locations)
84
+ return unless @verbose
85
+
86
+ _common_log(:debug, message, sticky: sticky, location: location, backtrace: backtrace)
87
+ end
88
+
89
+ # @param [Epuber::Compiler::FileTypes::AbstractFile] file
90
+ # @param [Fixnum] index
91
+ # @param [Fixnum] count
92
+ #
93
+ def start_processing_file(file, index, count)
94
+ @current_file = file
95
+
96
+ _common_log(:debug, "▸ Processing #{file.source_path} (#{index + 1} of #{count})", sticky: true)
97
+ end
98
+
99
+ def end_processing
100
+ _remove_sticky_message
101
+ @current_file = nil
102
+ end
103
+
104
+ # @param [String] info_text
105
+ #
106
+ def print_processing_debug_info(info_text)
107
+ return unless @verbose
108
+
109
+ message = if @current_file.nil?
110
+ "▸ #{info_text}"
111
+ else
112
+ "▸ #{@current_file.source_path}: #{info_text}"
113
+ end
114
+ _log(:debug, message)
115
+ end
116
+
117
+ # @param [String] step_name
118
+ # @param [Fixnum] time
119
+ #
120
+ def print_step_processing_time(step_name, time = nil)
121
+ return yield unless @debug_steps_times
122
+
123
+ if block_given?
124
+ start = Time.now
125
+ returned_value = yield
126
+
127
+ time = Time.now - start
128
+ end
129
+
130
+ info_text = "Step #{step_name} took #{(time * 1000).round(2)} ms"
131
+ message = if @current_file.nil?
132
+ "▸ #{info_text}"
133
+ else
134
+ "▸ #{@current_file.source_path}: #{info_text}"
135
+ end
136
+
137
+ _log(:debug, message)
138
+
139
+ returned_value
140
+ end
141
+
142
+ # Return true if there was any error logged
143
+ #
144
+ # @return [Boolean]
145
+ def error?
146
+ @error_was_logged
147
+ end
148
+
149
+ protected
150
+
151
+ # Point of implementation for concrete logger
152
+ #
153
+ # @param [Symbol] level
154
+ # @param [String] message
155
+ # @param [Epuber::Location, nil] location
156
+ # @param [Array<Thread::Backtrace::Location>, nil] backtrace
157
+ # @param [Boolean] sticky if true, the message will be sticky (will be always as the last message)
158
+ #
159
+ def _log(level, message, location: nil, backtrace: nil, remove_last: false) # rubocop:disable Lint/UnusedMethodArgument
160
+ raise 'Not implemented, this is abstract class'
161
+ end
162
+
163
+ # Remove last line of the output (if it was sticky)
164
+ #
165
+ # @return [String, nil] last line
166
+ #
167
+ def _remove_sticky_message; end
168
+
169
+ private
170
+
171
+ # Core logging method
172
+ #
173
+ # @param level [Symbol]
174
+ # @param message [String]
175
+ # @param location [Thread::Backtrace::Location, Epuber::Location, Nokogiri::XML::Node,
176
+ # Epuber::Compiler::FileTypes::AbstractFile, nil]
177
+ # @param sticky [Boolean] if true, the message will be sticky (will be always as the last message)
178
+ #
179
+ def _common_log(level, message, sticky: false, location: nil, backtrace: nil)
180
+ raise ArgumentError, "Unknown log level #{level}" unless LEVELS.include?(level)
181
+
182
+ @error_was_logged = true if level == :error
183
+
184
+ location = _location_from_obj(location)
185
+
186
+ if @verbose && level == :error
187
+ backtrace = location.try(:backtrace_locations) ||
188
+ message.try(:backtrace_locations) ||
189
+ backtrace ||
190
+ caller_locations
191
+ end
192
+
193
+ _log(level, message, location: location, backtrace: backtrace, sticky: sticky)
194
+ end
195
+
196
+ # @param [Thread::Backtrace::Location, Nokogiri::XML::Node] obj
197
+ #
198
+ # @return [Location]
199
+ #
200
+ def _location_from_obj(obj)
201
+ case obj
202
+ when ::Thread::Backtrace::Location
203
+ Location.new(path: obj.path, lineno: obj.lineno)
204
+ when ::Nokogiri::XML::Node
205
+ Location.new(path: obj.document.file_path, lineno: obj.line)
206
+ when Location
207
+ obj
208
+ when Epuber::Compiler::FileTypes::AbstractFile
209
+ Location.new(path: obj.source_path)
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end