2020-09-05 22:36:12 +00:00
|
|
|
require "json"
|
|
|
|
|
2019-02-17 19:25:23 +00:00
|
|
|
module Spectator
|
2021-02-13 05:46:22 +00:00
|
|
|
# Defines the file and line number a piece of code originated from.
|
|
|
|
struct Location
|
2019-02-17 19:25:23 +00:00
|
|
|
# Absolute file path.
|
|
|
|
getter file : String
|
|
|
|
|
2021-03-31 21:28:16 +00:00
|
|
|
# Starting line number in the file.
|
2019-02-17 19:25:23 +00:00
|
|
|
getter line : Int32
|
|
|
|
|
2021-03-31 21:28:16 +00:00
|
|
|
# Ending line number in the file.
|
|
|
|
getter end_line : Int32
|
|
|
|
|
2021-02-13 05:46:22 +00:00
|
|
|
# Creates the location.
|
2021-03-31 21:28:16 +00:00
|
|
|
def initialize(@file, @line, end_line = nil)
|
|
|
|
# if an end line is not provided,
|
|
|
|
# make the end line the same as the start line
|
|
|
|
@end_line = end_line || @line
|
2019-02-17 19:25:23 +00:00
|
|
|
end
|
|
|
|
|
2021-02-13 05:46:22 +00:00
|
|
|
# Parses a location from a string.
|
2021-01-01 01:45:56 +00:00
|
|
|
# The *string* should be in the form:
|
|
|
|
# ```text
|
|
|
|
# FILE:LINE
|
|
|
|
# ```
|
|
|
|
# This matches the output of the `#to_s` method.
|
2019-03-24 02:47:41 +00:00
|
|
|
def self.parse(string)
|
|
|
|
# Make sure to handle multiple colons.
|
|
|
|
# If this ran on Windows, there's a possibility of a colon in the path.
|
|
|
|
# The last element should always be the line number.
|
|
|
|
parts = string.split(':')
|
|
|
|
path = parts[0...-1].join(':')
|
|
|
|
line = parts.last
|
|
|
|
file = File.expand_path(path)
|
|
|
|
self.new(file, line.to_i)
|
|
|
|
end
|
|
|
|
|
2019-02-18 04:23:57 +00:00
|
|
|
# The relative path to the file from the current directory.
|
|
|
|
# If the file isn't in the current directory or a sub-directory,
|
|
|
|
# then the absolute path is provided.
|
|
|
|
def path
|
|
|
|
# Add the path separator here.
|
|
|
|
# Otherwise, things like:
|
|
|
|
# `spectator/foo.cr` and `spectator.cr` overlap.
|
|
|
|
# It also makes the substring easier.
|
|
|
|
cwd = Dir.current + File::SEPARATOR
|
|
|
|
if file.starts_with?(cwd)
|
|
|
|
# Relative to the current directory.
|
|
|
|
# Trim the current directory path from the beginning.
|
|
|
|
file[cwd.size..-1]
|
|
|
|
else
|
|
|
|
# Not trivial to find the file.
|
|
|
|
# Return the absolute path.
|
|
|
|
file
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-02-13 05:46:22 +00:00
|
|
|
# String representation of the location.
|
2019-02-18 06:01:43 +00:00
|
|
|
# This is formatted as:
|
|
|
|
# ```text
|
|
|
|
# FILE:LINE
|
|
|
|
# ```
|
2019-02-17 19:25:23 +00:00
|
|
|
def to_s(io)
|
2019-02-18 04:23:57 +00:00
|
|
|
io << path
|
2019-02-17 19:25:23 +00:00
|
|
|
io << ':'
|
|
|
|
io << line
|
|
|
|
end
|
2019-03-23 03:29:20 +00:00
|
|
|
|
2021-02-13 05:46:22 +00:00
|
|
|
# Creates the JSON representation of the location.
|
2019-03-23 03:29:20 +00:00
|
|
|
def to_json(json : ::JSON::Builder)
|
|
|
|
json.string(to_s)
|
|
|
|
end
|
2019-02-17 19:25:23 +00:00
|
|
|
end
|
|
|
|
end
|