gloss 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitattributes +3 -0
- data/.github/workflows/{crystal.yml → crystal_specs.yml} +1 -1
- data/.github/workflows/{ruby.yml → ruby_specs.yml} +2 -2
- data/.gloss.yml +1 -0
- data/.rspec +1 -0
- data/Gemfile.lock +10 -12
- data/README.md +36 -5
- data/Rakefile +1 -1
- data/exe/gloss +13 -2
- data/ext/gloss/Makefile +8 -19
- data/ext/gloss/{src/lib → lib}/cr_ruby.cr +0 -0
- data/ext/gloss/lib/rbs_types.cr +3 -0
- data/ext/gloss/spec/parser_spec.cr +83 -83
- data/ext/gloss/src/cr_ast.cr +96 -77
- data/ext/gloss/src/gloss.cr +2 -2
- data/ext/gloss/src/lexer.cr +59 -1
- data/ext/gloss/src/rb_ast.cr +114 -63
- data/lib/gloss.rb +15 -7
- data/lib/gloss/cli.rb +85 -28
- data/lib/gloss/config.rb +13 -7
- data/lib/gloss/errors.rb +3 -4
- data/lib/gloss/initializer.rb +9 -9
- data/lib/gloss/logger.rb +29 -0
- data/lib/gloss/parser.rb +19 -5
- data/lib/gloss/prog_loader.rb +141 -0
- data/lib/gloss/scope.rb +7 -2
- data/lib/gloss/source.rb +17 -14
- data/lib/gloss/type_checker.rb +86 -33
- data/lib/gloss/utils.rb +44 -0
- data/lib/gloss/version.rb +1 -2
- data/lib/gloss/visitor.rb +667 -0
- data/lib/gloss/watcher.rb +51 -16
- data/lib/gloss/writer.rb +24 -15
- data/sig/core.rbs +2 -0
- data/sig/fast_blank.rbs +4 -0
- data/sig/{gloss.rbs → gls.rbs} +0 -0
- data/sig/listen.rbs +1 -0
- data/sig/optparse.rbs +6 -0
- data/sig/rubygems.rbs +9 -0
- data/sig/yaml.rbs +3 -0
- data/src/exe/gloss +19 -0
- data/src/lib/gloss.gl +26 -0
- data/src/lib/gloss/cli.gl +70 -0
- data/src/lib/gloss/config.gl +9 -3
- data/src/lib/gloss/initializer.gl +4 -6
- data/src/lib/gloss/logger.gl +21 -0
- data/src/lib/gloss/parser.gl +17 -5
- data/src/lib/gloss/prog_loader.gl +133 -0
- data/src/lib/gloss/scope.gl +7 -0
- data/src/lib/gloss/source.gl +32 -0
- data/src/lib/gloss/type_checker.gl +85 -36
- data/src/lib/gloss/utils.gl +38 -0
- data/src/lib/gloss/version.gl +1 -1
- data/src/lib/gloss/visitor.gl +575 -0
- data/src/lib/gloss/watcher.gl +44 -10
- data/src/lib/gloss/writer.gl +16 -14
- metadata +28 -8
- data/lib/gloss/builder.rb +0 -447
data/lib/gloss/watcher.rb
CHANGED
@@ -1,41 +1,76 @@
|
|
1
|
-
# frozen_string_literal: true
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See src/ to make changes
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
5
|
|
6
6
|
require "listen"
|
7
7
|
module Gloss
|
8
8
|
class Watcher
|
9
|
-
def initialize()
|
10
|
-
@paths =
|
9
|
+
def initialize(paths)
|
10
|
+
@paths = paths
|
11
|
+
(if @paths.empty?
|
12
|
+
@paths = [File.join(Dir.pwd, Config.src_dir)]
|
13
|
+
@only = /(?:(\.gl|(?:(?<=\/)[^\.\/]+))\z|\A[^\.\/]+\z)/
|
14
|
+
else
|
15
|
+
file_names = Array.new
|
16
|
+
paths = Array.new
|
17
|
+
@paths.each() { |pa|
|
18
|
+
pn = Pathname.new(pa)
|
19
|
+
paths.<<(pn.parent
|
20
|
+
.to_s)
|
21
|
+
file_names.<<((if pn.file?
|
22
|
+
pn.basename
|
23
|
+
.to_s
|
24
|
+
else
|
25
|
+
pa
|
26
|
+
end))
|
27
|
+
}
|
28
|
+
@paths = paths.uniq
|
29
|
+
@only = /#{Regexp.union(file_names)}/
|
30
|
+
end)
|
11
31
|
end
|
12
32
|
def watch()
|
13
|
-
|
14
|
-
|
33
|
+
Gloss.logger
|
34
|
+
.info("Now listening for changes in #{@paths.join(", ")}")
|
35
|
+
listener = Listen.to(*@paths, latency: 2, only: @only) { |modified, added, removed|
|
15
36
|
modified.+(added)
|
16
|
-
.each { |f|
|
37
|
+
.each() { |f|
|
38
|
+
Gloss.logger
|
39
|
+
.info("Rewriting #{f}")
|
17
40
|
content = File.read(f)
|
18
|
-
|
41
|
+
err = catch(:"error") { ||
|
42
|
+
Writer.new(Visitor.new(Parser.new(content)
|
43
|
+
.run)
|
19
44
|
.run, f)
|
20
45
|
.run
|
46
|
+
nil }
|
47
|
+
(if err
|
48
|
+
Gloss.logger
|
49
|
+
.error(err)
|
50
|
+
else
|
51
|
+
Gloss.logger
|
52
|
+
.info("Done")
|
53
|
+
end)
|
21
54
|
}
|
22
|
-
removed.each { |f|
|
55
|
+
removed.each() { |f|
|
23
56
|
out_path = Utils.src_path_to_output_path(f)
|
57
|
+
Gloss.logger
|
58
|
+
.info("Removing #{out_path}")
|
24
59
|
(if File.exist?(out_path)
|
25
60
|
File.delete(out_path)
|
26
61
|
end)
|
62
|
+
Gloss.logger
|
63
|
+
.info("Done")
|
27
64
|
}
|
28
65
|
}
|
29
|
-
listener.start
|
30
66
|
begin
|
31
|
-
|
32
|
-
|
33
|
-
}
|
67
|
+
listener.start
|
68
|
+
sleep
|
34
69
|
rescue Interrupt
|
35
|
-
|
70
|
+
Gloss.logger
|
71
|
+
.info("Interrupt signal received, shutting down")
|
36
72
|
exit(0)
|
37
73
|
end
|
38
74
|
end
|
39
75
|
end
|
40
76
|
end
|
41
|
-
|
data/lib/gloss/writer.rb
CHANGED
@@ -1,23 +1,15 @@
|
|
1
|
-
# frozen_string_literal: true
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See src/ to make changes
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
5
|
|
6
6
|
require "pathname"
|
7
7
|
require "fileutils"
|
8
8
|
module Gloss
|
9
|
-
module Utils
|
10
|
-
module_function
|
11
|
-
def src_path_to_output_path(src_path)
|
12
|
-
src_path.sub(/\A(?:\.\/)?#{Config.src_dir}\/?/, "")
|
13
|
-
.sub(/\.gl$/, ".rb")
|
14
|
-
end
|
15
|
-
end
|
16
9
|
class Writer
|
17
|
-
|
18
|
-
def initialize(content, src_path, output_path = Pathname.new(src_path_to_output_path(src_path))
|
19
|
-
)
|
10
|
+
def initialize(content, src_path, output_path = Pathname.new(Utils.src_path_to_output_path(src_path)))
|
20
11
|
@content = content
|
12
|
+
@src_path = src_path
|
21
13
|
@output_path = output_path
|
22
14
|
end
|
23
15
|
def run()
|
@@ -26,9 +18,26 @@ module Gloss
|
|
26
18
|
FileUtils.mkdir_p(@output_path.parent)
|
27
19
|
end
|
28
20
|
File.open(@output_path, "wb") { |file|
|
29
|
-
|
21
|
+
sb = shebang
|
22
|
+
(if sb
|
23
|
+
file.puts(sb)
|
24
|
+
end)
|
25
|
+
file.puts(@content)
|
30
26
|
}
|
31
27
|
end
|
28
|
+
private def shebang()
|
29
|
+
(if @output_path.executable?
|
30
|
+
first_line = File.open(@src_path) { |f|
|
31
|
+
f.readline
|
32
|
+
}
|
33
|
+
(if first_line.start_with?("#!")
|
34
|
+
first_line
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end)
|
38
|
+
else
|
39
|
+
nil
|
40
|
+
end)
|
41
|
+
end
|
32
42
|
end
|
33
43
|
end
|
34
|
-
|
data/sig/core.rbs
ADDED
data/sig/fast_blank.rbs
ADDED
data/sig/{gloss.rbs → gls.rbs}
RENAMED
File without changes
|
data/sig/listen.rbs
CHANGED
data/sig/optparse.rbs
ADDED
data/sig/rubygems.rbs
ADDED
data/sig/yaml.rbs
ADDED
data/src/exe/gloss
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gloss"
|
5
|
+
|
6
|
+
begin
|
7
|
+
Gloss::CLI.new(ARGV).run
|
8
|
+
rescue SystemExit
|
9
|
+
# raised by `abort` or `exit`; no op
|
10
|
+
rescue => e
|
11
|
+
abort <<~MSG
|
12
|
+
Unexpected error: #{e.class.name}
|
13
|
+
Message: #{e.message}
|
14
|
+
Trace:
|
15
|
+
#{e.backtrace.join("\n")}
|
16
|
+
|
17
|
+
This is probably a bug and may warrant a bug report at https://github.com/johansenja/gloss/issues
|
18
|
+
MSG
|
19
|
+
end
|
data/src/lib/gloss.gl
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "rbs"
|
2
|
+
require "json"
|
3
|
+
require "steep"
|
4
|
+
require "fast_blank"
|
5
|
+
|
6
|
+
require "gloss/version"
|
7
|
+
require "gloss/cli"
|
8
|
+
require "gloss/watcher"
|
9
|
+
require "gloss/type_checker"
|
10
|
+
require "gloss/parser"
|
11
|
+
require "gloss/initializer"
|
12
|
+
require "gloss/config"
|
13
|
+
require "gloss/writer"
|
14
|
+
require "gloss/source"
|
15
|
+
require "gloss/scope"
|
16
|
+
require "gloss/visitor"
|
17
|
+
require "gloss/errors"
|
18
|
+
require "gloss/logger"
|
19
|
+
require "gloss/prog_loader"
|
20
|
+
require "gloss/utils"
|
21
|
+
|
22
|
+
is_ci = ENV.fetch("CI") { false }
|
23
|
+
require "gls" unless is_ci # a bit of a hack for now
|
24
|
+
|
25
|
+
EMPTY_ARRAY = Array.new.freeze
|
26
|
+
EMPTY_HASH = {}.freeze
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
class CLI
|
5
|
+
def initialize(argv)
|
6
|
+
@argv = argv
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
# TODO: allow destructuring: command, *files = @argv
|
11
|
+
command = @argv.first
|
12
|
+
files = @argv[1..-1]
|
13
|
+
err_msg = catch :error do
|
14
|
+
case command
|
15
|
+
when "init"
|
16
|
+
force = false
|
17
|
+
OptionParser.new do |opt|
|
18
|
+
opt.on("--force", "-f") { force = true }
|
19
|
+
end.parse(@argv)
|
20
|
+
Initializer.new(force).run
|
21
|
+
when "version", "--version", "-v"
|
22
|
+
puts Gloss::VERSION
|
23
|
+
when "watch", "build"
|
24
|
+
type_checker = ProgLoader.new.run
|
25
|
+
if command == "watch"
|
26
|
+
files = files.map do |f|
|
27
|
+
path = Pathname.new(f).absolute? ? f : File.join(Dir.pwd, f)
|
28
|
+
if Pathname.new(path).exist?
|
29
|
+
path
|
30
|
+
else
|
31
|
+
throw :error, "Pathname #{f} does not exist"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
Watcher.new(files).watch
|
35
|
+
elsif command == "build"
|
36
|
+
entry_tree = Parser.new(File.read(Config.entrypoint)).run
|
37
|
+
Visitor.new(entry_tree, type_checker).run
|
38
|
+
files = Dir.glob("#{Config.src_dir}/**/*.gl") if files.empty?
|
39
|
+
files.each do |fp|
|
40
|
+
fp = File.absolute_path(fp)
|
41
|
+
preloaded_output = OUTPUT_BY_PATH.fetch(fp) { nil }
|
42
|
+
if preloaded_output
|
43
|
+
rb_output = preloaded_output
|
44
|
+
else
|
45
|
+
Gloss.logger.info "Building #{fp}"
|
46
|
+
content = File.read(fp)
|
47
|
+
tree_hash = Parser.new(content).run
|
48
|
+
rb_output = Visitor.new(tree_hash, type_checker).run
|
49
|
+
end
|
50
|
+
Gloss.logger.info "Type checking #{fp}"
|
51
|
+
type_checker.run(fp, rb_output)
|
52
|
+
end
|
53
|
+
# ensure all files are type checked before anything is written
|
54
|
+
files.each do |fp|
|
55
|
+
fp = File.absolute_path(fp)
|
56
|
+
rb_output = OUTPUT_BY_PATH.fetch(fp)
|
57
|
+
Gloss.logger.info "Writing #{fp}"
|
58
|
+
Writer.new(rb_output, fp).run
|
59
|
+
end
|
60
|
+
end
|
61
|
+
else
|
62
|
+
throw :error, "Gloss doesn't know how to #{command}"
|
63
|
+
end
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
abort err_msg if err_msg
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/src/lib/gloss/config.gl
CHANGED
@@ -1,15 +1,21 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "ostruct"
|
4
2
|
require "yaml"
|
5
3
|
|
6
4
|
module Gloss
|
7
|
-
|
5
|
+
CONFIG_PATH = ".gloss.yml"
|
8
6
|
Config = OpenStruct.new(
|
9
7
|
default_config: {
|
10
8
|
frozen_string_literals: true,
|
11
9
|
src_dir: "src",
|
10
|
+
entrypoint: nil,
|
11
|
+
strict_require: false
|
12
12
|
}
|
13
13
|
)
|
14
|
+
|
15
|
+
user_config = if File.exist?(CONFIG_PATH)
|
16
|
+
YAML.safe_load(File.read(CONFIG_PATH))
|
17
|
+
else
|
18
|
+
Config.default_config
|
19
|
+
end
|
14
20
|
Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
|
15
21
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "yaml"
|
4
2
|
|
5
3
|
module Gloss
|
@@ -8,15 +6,15 @@ module Gloss
|
|
8
6
|
end
|
9
7
|
|
10
8
|
def run
|
11
|
-
if File.exist?(
|
12
|
-
|
9
|
+
if File.exist?(CONFIG_PATH) && !@force
|
10
|
+
throw :error, "#{CONFIG_PATH} file already exists - aborting. Use --force to override."
|
13
11
|
end
|
14
12
|
|
15
|
-
File.open(
|
13
|
+
File.open(CONFIG_PATH, "wb") do |file|
|
16
14
|
file.puts Config.default_config.transform_keys(&:to_s).to_yaml
|
17
15
|
end
|
18
16
|
|
19
|
-
|
17
|
+
Gloss.logger.info "Created #{CONFIG_PATH} with default preferences"
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gloss
|
2
|
+
def self.logger
|
3
|
+
if @logger
|
4
|
+
@logger
|
5
|
+
else
|
6
|
+
env_log_level = ENV.fetch("LOG_LEVEL") { "INFO" }
|
7
|
+
real_log_level = {
|
8
|
+
"UNKNOWN" => Logger::UNKNOWN,
|
9
|
+
"FATAL" => Logger::FATAL,
|
10
|
+
"ERROR" => Logger::ERROR,
|
11
|
+
"WARN" => Logger::WARN,
|
12
|
+
"INFO" => Logger::INFO,
|
13
|
+
"DEBUG" => Logger::DEBUG,
|
14
|
+
"NIL" => nil,
|
15
|
+
nil => nil,
|
16
|
+
"" => nil
|
17
|
+
}.fetch env_log_level
|
18
|
+
@logger = Logger.new(real_log_level ? STDOUT : IO::NULL)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/src/lib/gloss/parser.gl
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Gloss
|
4
2
|
class Parser
|
5
3
|
def initialize(@str : String)
|
@@ -10,9 +8,23 @@ module Gloss
|
|
10
8
|
begin
|
11
9
|
JSON.parse tree_json, symbolize_names: true
|
12
10
|
rescue JSON::ParserError
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
error_message = tree_json
|
12
|
+
error_message.match /.+\s:(\d+)$/
|
13
|
+
if $1
|
14
|
+
line_number = $1.to_i
|
15
|
+
# line numbers start at 1, but array index starts at 0; so this still gives one line
|
16
|
+
# either side of the offending line
|
17
|
+
context = @str.lines[(line_number - 2)..(line_number)].map.with_index { |line, index|
|
18
|
+
"#{index - 1 + line_number}| #{line}"
|
19
|
+
}.join
|
20
|
+
error_message = <<~MSG
|
21
|
+
#{context.rstrip}
|
22
|
+
|
23
|
+
#{error_message}
|
24
|
+
|
25
|
+
MSG
|
26
|
+
end
|
27
|
+
throw :error, error_message
|
16
28
|
end
|
17
29
|
end
|
18
30
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require "rubygems/gem_runner"
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
OUTPUT_BY_PATH = Hash.new
|
5
|
+
|
6
|
+
class ProgLoader
|
7
|
+
def initialize
|
8
|
+
entrypoint = Config.entrypoint
|
9
|
+
if entrypoint == nil || entrypoint == ""
|
10
|
+
throw :error, "Entrypoint is not yet set in .gloss.yml"
|
11
|
+
end
|
12
|
+
@files_to_process = [
|
13
|
+
Utils.absolute_path(Config.entrypoint),
|
14
|
+
# __dir__ is typed as String? - but it shouldn't be nil here
|
15
|
+
Utils.absolute_path(File.join((__dir__||""), "..", "..", "sig", "core.rbs"))
|
16
|
+
]
|
17
|
+
@processed_files = Set.new
|
18
|
+
@type_checker = TypeChecker.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
@files_to_process.each do |path_string|
|
23
|
+
# currently steep would give an `unexpected jump` if next was used
|
24
|
+
unless @processed_files.member?(path_string) || OUTPUT_BY_PATH.[](path_string)
|
25
|
+
Gloss.logger.debug "Loading #{path_string}"
|
26
|
+
path = Utils.absolute_path(path_string)
|
27
|
+
file_contents = File.open(path).read
|
28
|
+
contents_tree = Parser.new(file_contents).run
|
29
|
+
on_new_file_referenced = proc do |pa, relative|
|
30
|
+
if relative
|
31
|
+
handle_require_relative pa
|
32
|
+
else
|
33
|
+
handle_require pa
|
34
|
+
end
|
35
|
+
end
|
36
|
+
OUTPUT_BY_PATH.[](path_string) = Visitor.new(contents_tree, @type_checker, on_new_file_referenced).run
|
37
|
+
@processed_files.add path_string
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@type_checker
|
42
|
+
end
|
43
|
+
|
44
|
+
STDLIB_TYPE_DEPENDENCIES = {
|
45
|
+
"yaml" => %w[pstore dbm],
|
46
|
+
"rbs" => %w[logger set tsort],
|
47
|
+
"logger" => %w[monitor],
|
48
|
+
}
|
49
|
+
|
50
|
+
private def handle_require(path)
|
51
|
+
if path.start_with? "."
|
52
|
+
base = File.join(Dir.pwd, path)
|
53
|
+
fp = base + ".gl"
|
54
|
+
if File.exist? fp
|
55
|
+
@files_to_process << fp
|
56
|
+
end
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
# look for .gl file if the "require" refers to the lib directory of current project dir
|
61
|
+
full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
|
62
|
+
pathn = Pathname.new full
|
63
|
+
if pathn.file?
|
64
|
+
@files_to_process << pathn.to_s
|
65
|
+
else
|
66
|
+
# no .gl file available - .rbs file available?
|
67
|
+
# TODO: verify file is still actually requireable
|
68
|
+
pathn = Pathname.new("#{File.join(Dir.pwd, "sig", path)}.rbs")
|
69
|
+
gem_path = Utils.gem_path_for(path)
|
70
|
+
if gem_path
|
71
|
+
sig_files = Dir.glob(File.absolute_path(File.join(gem_path, "..", "..", "sig", "**", "*.rbs")))
|
72
|
+
if sig_files.length.positive?
|
73
|
+
sig_files.each do |fp|
|
74
|
+
@type_checker.load_sig_path fp
|
75
|
+
end
|
76
|
+
@processed_files.add path
|
77
|
+
rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { nil }
|
78
|
+
if rbs_type_deps
|
79
|
+
rbs_type_deps.each { |d| handle_require d }
|
80
|
+
end
|
81
|
+
return
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
if pathn.file?
|
86
|
+
@type_checker.load_sig_path(pathn.to_s)
|
87
|
+
@processed_files.add pathn.to_s
|
88
|
+
else
|
89
|
+
rbs_stdlib_dir = File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", path))
|
90
|
+
if Pathname.new(rbs_stdlib_dir).exist?
|
91
|
+
load_rbs_from_require_path(path)
|
92
|
+
rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { nil }
|
93
|
+
if rbs_type_deps
|
94
|
+
rbs_type_deps.each { |d| load_rbs_from_require_path d }
|
95
|
+
end
|
96
|
+
elsif Config.strict_require
|
97
|
+
throw :error, "Cannot resolve require path for #{path}"
|
98
|
+
else
|
99
|
+
Gloss.logger.debug "No path found for #{path}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private def handle_require_relative(path)
|
106
|
+
base = File.join(@filepath, "..", path)
|
107
|
+
pn : String? = nil
|
108
|
+
Gem.suffixes.each do |ext|
|
109
|
+
full = File.absolute_path(base + ext)
|
110
|
+
pn = full if File.exist?(full)
|
111
|
+
end
|
112
|
+
|
113
|
+
if pn
|
114
|
+
@files_to_process << pn unless @files_to_process.include? pn
|
115
|
+
elsif Config.strict_require
|
116
|
+
throw :error, "Cannot resolve require path for #{pn}"
|
117
|
+
else
|
118
|
+
Gloss.logger.debug "No path found for #{path}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private def rbs_stdlib_path_for(libr)
|
123
|
+
File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", libr))
|
124
|
+
end
|
125
|
+
|
126
|
+
private def load_rbs_from_require_path(path)
|
127
|
+
Dir.glob(File.join(rbs_stdlib_path_for(path), "**", "*.rbs")).each do |fp|
|
128
|
+
@type_checker.load_sig_path(fp)
|
129
|
+
@processed_files.add fp
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|