gloss 0.1.1 → 0.1.6

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.
data/lib/gloss/parser.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Parser
@@ -1,42 +1,58 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "rubygems/gem_runner"
7
6
  module Gloss
8
7
  OUTPUT_BY_PATH = Hash.new
9
8
  class ProgLoader
10
- def initialize()
11
- entrypoint = Config.entrypoint
12
- (if entrypoint.==(nil) || entrypoint.==("")
9
+ attr_reader(:"type_checker")
10
+ def initialize(entrypoint_path = nil, entrypoint_contents = nil)
11
+ entrypoint_path ||= Config.entrypoint
12
+ (if entrypoint_path.==(nil) || entrypoint_path.==("")
13
13
  throw(:"error", "Entrypoint is not yet set in .gloss.yml")
14
14
  end)
15
- @files_to_process = [Utils.absolute_path(Config.entrypoint), Utils.absolute_path(File.join(__dir__ || "", "..", "..", "sig", "core.rbs"))]
15
+ entrypoint = (if entrypoint_path && entrypoint_contents
16
+ ep = (if entrypoint_path.==(Runtime::NON_EXISTENT_FILEPATH)
17
+ entrypoint_path
18
+ else
19
+ Utils.absolute_path(entrypoint_path)
20
+ end)
21
+ [ep, entrypoint_contents]
22
+ else
23
+ Utils.abs_path_with_contents(entrypoint_path)
24
+ end)
25
+ core_types = Utils.abs_path_with_contents(File.join(__dir__ || "", "..", "..", "sig", "core.rbs"))
26
+ @files_to_process = [entrypoint, core_types]
16
27
  @processed_files = Set.new
17
28
  @type_checker = TypeChecker.new
18
29
  end
19
30
  def run()
20
- @files_to_process.each() { |path_string|
21
- unless @processed_files.member?(path_string) || OUTPUT_BY_PATH.[](path_string)
22
- Gloss.logger
31
+ @files_to_process.each() { |__arg0|
32
+ path_string = __arg0.[](0)
33
+ file_contents = __arg0.[](1)
34
+ (if path_string.end_with?(".rbs")
35
+ @type_checker.load_sig_path(path_string)
36
+ else
37
+ (if !@processed_files.member?(path_string) || !OUTPUT_BY_PATH.[](path_string)
38
+ Gloss.logger
23
39
  .debug("Loading #{path_string}")
24
- path = Utils.absolute_path(path_string)
25
- file_contents = File.open(path)
26
- .read
27
- contents_tree = Parser.new(file_contents)
40
+ contents_tree = Parser.new(file_contents)
28
41
  .run
29
- on_new_file_referenced = proc() { |pa, relative|
30
- (if relative
31
- handle_require_relative(pa)
32
- else
33
- handle_require(pa)
34
- end)
35
- }
36
- OUTPUT_BY_PATH.[]=(path_string, Visitor.new(contents_tree, @type_checker, on_new_file_referenced)
42
+ on_new_file_referenced = proc() { |ps, relative|
43
+ ps.each() { |pa|
44
+ (if relative
45
+ handle_require_relative(pa, path_string)
46
+ else
47
+ handle_require(pa)
48
+ end)
49
+ }
50
+ }
51
+ OUTPUT_BY_PATH.[]=(path_string, Visitor.new(contents_tree, @type_checker, on_new_file_referenced)
37
52
  .run)
38
- @processed_files.add(path_string)
39
- end
53
+ @processed_files.add(path_string)
54
+ end)
55
+ end)
40
56
  }
41
57
  @type_checker
42
58
  end
@@ -48,19 +64,19 @@ module Gloss
48
64
  base = File.join(Dir.pwd, path)
49
65
  fp = base.+(".gl")
50
66
  (if File.exist?(fp)
51
- @files_to_process.<<(fp)
67
+ @files_to_process.<<(Utils.abs_path_with_contents(fp))
52
68
  end)
53
69
  return
54
70
  end)
55
71
  full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
56
72
  pathn = Pathname.new(full)
57
73
  (if pathn.file?
58
- @files_to_process.<<(pathn.to_s)
74
+ @files_to_process.<<(Utils.abs_path_with_contents(pathn.to_s))
59
75
  else
60
76
  pathn = Pathname.new("#{File.join(Dir.pwd, "sig", path)}.rbs")
61
77
  gem_path = Utils.gem_path_for(path)
62
78
  (if gem_path
63
- sig_files = Dir.glob(File.absolute_path(File.join(gem_path, "..", "..", "sig", "**", "*.rbs")))
79
+ sig_files = Dir.glob(File.absolute_path(File.join(gem_path, "..", "sig", "**", "*.rbs")))
64
80
  (if sig_files.length
65
81
  .positive?
66
82
  sig_files.each() { |fp|
@@ -81,7 +97,7 @@ return
81
97
  @type_checker.load_sig_path(pathn.to_s)
82
98
  @processed_files.add(pathn.to_s)
83
99
  else
84
- rbs_stdlib_dir = File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", path))
100
+ rbs_stdlib_dir = File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "stdlib", path))
85
101
  (if Pathname.new(rbs_stdlib_dir)
86
102
  .exist?
87
103
  load_rbs_from_require_path(path)
@@ -103,24 +119,27 @@ nil }
103
119
  end)
104
120
  end)
105
121
  end
106
- private def handle_require_relative(path)
107
- base = File.join(@filepath, "..", path)
122
+ private def handle_require_relative(path, source_file)
123
+ base = File.join(source_file, "..", path)
108
124
  # @type var pn: String?
109
125
  pn = nil
110
- Gem.suffixes
111
- .each() { |ext|
126
+ exts = [".gl"].concat(Gem.suffixes)
127
+ exts.each() { |ext|
112
128
  full = File.absolute_path(base.+(ext))
113
129
  (if File.exist?(full)
114
130
  pn = full
115
131
  end)
116
132
  }
117
133
  (if pn
118
- unless @files_to_process.include?(pn)
119
- @files_to_process.<<(pn)
134
+ unless @files_to_process.any?() { |__arg1|
135
+ fp = __arg1.[](0)
136
+ fp.==(pn)
137
+ }
138
+ @files_to_process.<<(Utils.abs_path_with_contents(pn))
120
139
  end
121
140
  else
122
141
  (if Config.strict_require
123
- throw(:"error", "Cannot resolve require path for #{pn}")
142
+ throw(:"error", "Cannot resolve relative path for #{path}")
124
143
  else
125
144
  Gloss.logger
126
145
  .debug("No path found for #{path}")
@@ -128,7 +147,7 @@ nil }
128
147
  end)
129
148
  end
130
149
  private def rbs_stdlib_path_for(libr)
131
- File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", libr))
150
+ File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "stdlib", libr))
132
151
  end
133
152
  private def load_rbs_from_require_path(path)
134
153
  Dir.glob(File.join(rbs_stdlib_path_for(path), "**", "*.rbs"))
@@ -0,0 +1,25 @@
1
+
2
+ ##### This file was generated by Gloss; any changes made here will be overwritten.
3
+ ##### See / to make changes
4
+
5
+ require "stringio"
6
+ module Gloss
7
+ class Runtime
8
+ NON_EXISTENT_FILEPATH = "__string__"
9
+ def self.process_string(str, options = Config.default_config)
10
+ out_io = StringIO.new
11
+ error_msg = catch(:"error") { ||
12
+ tree = Parser.new(str)
13
+ .run
14
+ tc = ProgLoader.new(NON_EXISTENT_FILEPATH, str)
15
+ .run
16
+ rb_output = Visitor.new(tree, tc)
17
+ .run
18
+ tc.run(NON_EXISTENT_FILEPATH, rb_output)
19
+ Writer.new(rb_output, NON_EXISTENT_FILEPATH, out_io)
20
+ .run
21
+ nil }
22
+ return [out_io.string, error_msg].freeze
23
+ end
24
+ end
25
+ end
data/lib/gloss/scope.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Scope < Hash
data/lib/gloss/source.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Source < String
@@ -1,18 +1,27 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "set"
7
6
  module Gloss
8
7
  class TypeChecker
9
- Project = Struct.new(:"targets")
10
8
  attr_reader(:"steep_target", :"top_level_decls", :"env", :"rbs_gem_dir")
9
+ module Strictness
10
+ Strict = "strict"
11
+ Lenient = "lenient"
12
+ Default = "default"
13
+ end
11
14
  def initialize()
12
- @steep_target = Steep::Project::Target.new(name: "gloss", options: Steep::Project::Options.new
13
- .tap() { |o|
14
- o.allow_unknown_constant_assignment=(true)
15
- }, source_patterns: ["**/*.rb"], ignore_patterns: Array.new, signature_patterns: ["sig"])
15
+ options = Steep::Project::Options.new
16
+ case Config.type_checking_strictness
17
+ when Strictness::Strict
18
+ options.apply_strict_typing_options!
19
+ when Strictness::Lenient
20
+ options.apply_lenient_typing_options!
21
+ else
22
+ options.apply_default_typing_options!
23
+ end
24
+ @steep_target = Steep::Project::Target.new(name: "gloss", options: options, source_patterns: ["**/*.rb"], ignore_patterns: Array.new, signature_patterns: ["sig"])
16
25
  @top_level_decls = Set.new
17
26
  @rbs_gem_dir = Utils.gem_path_for("rbs")
18
27
  env_loader = RBS::EnvironmentLoader.new
@@ -51,7 +60,7 @@ case e
51
60
  when Steep::Diagnostic::Ruby::UnexpectedBlockGiven
52
61
  "Unexpected block given"
53
62
  else
54
- "#{e.header_line}\n#{e.inspect}"
63
+ "#{e.header_line}\n#{e}"
55
64
  end
56
65
  }
57
66
  .join("\n")
data/lib/gloss/utils.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "rubygems"
7
6
  module Gloss
@@ -21,17 +20,11 @@ module Gloss
21
20
  end)
22
21
  end
23
22
  def gem_path_for(gem_name)
24
- begin
25
- Gem.ui
26
- .instance_variable_set(:"@outs", StringIO.new)
27
- Gem::GemRunner.new
28
- .run(["which", gem_name])
29
- Gem.ui
30
- .outs
31
- .string
32
- rescue SystemExit => e
33
- nil
34
- end
23
+ spec = Gem::Specification.find_by_path(gem_name)
24
+ (if spec
25
+ spec.full_require_paths
26
+ .first
27
+ end)
35
28
  end
36
29
  def with_file_header(str)
37
30
  "#{Visitor::FILE_HEADER}\n\n#{str}"
@@ -40,5 +33,10 @@ module Gloss
40
33
  src_path.sub("#{Config.src_dir}/", "")
41
34
  .sub(/\.gl$/, ".rb")
42
35
  end
36
+ def abs_path_with_contents(path)
37
+ abs_path = absolute_path(path)
38
+ return [abs_path, File.open(abs_path)
39
+ .read].freeze
40
+ end
43
41
  end
44
42
  end
data/lib/gloss/version.rb CHANGED
@@ -1,8 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
- ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
1
+
2
+ ##### This file was generated by Gloss; any changes made here will be overwritten.
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
- VERSION = "0.1.1"
6
+ VERSION = "0.1.6"
8
7
  end
data/lib/gloss/visitor.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Visitor
@@ -123,7 +122,7 @@ case node.[](:"type")
123
122
  else
124
123
  RBS::Types::Bases::Any.new(location: build_location(node))
125
124
  end)
126
- method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: args.dig(:"types", :"required_positionals"), optional_positionals: args.dig(:"types", :"optional_positionals"), rest_positionals: args.dig(:"types", :"rest_positionals"), trailing_positionals: args.dig(:"types", :"trailing_positionals"), required_keywords: args.dig(:"types", :"required_keywords"), optional_keywords: args.dig(:"types", :"optional_keywords"), rest_keywords: args.dig(:"types", :"rest_keywords"), return_type: return_type), block: (if node.[](:"yield_arg_count")
125
+ method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: args.dig(:"types", :"required_positionals"), optional_positionals: args.dig(:"types", :"optional_positionals"), rest_positionals: args.dig(:"types", :"rest_positionals"), trailing_positionals: args.dig(:"types", :"trailing_positionals"), required_keywords: args.dig(:"types", :"required_keywords"), optional_keywords: args.dig(:"types", :"optional_keywords"), rest_keywords: args.dig(:"types", :"rest_keywords"), return_type: return_type), block: (if node.[](:"yield_arg_count") || args.dig(:"types", :"block_arg")
127
126
  RBS::Types::Block.new(type: RBS::Types::Function.new(required_positionals: Array.new, optional_positionals: Array.new, rest_positionals: nil, trailing_positionals: Array.new, required_keywords: Hash.new, optional_keywords: Hash.new, rest_keywords: nil, return_type: RBS::Types::Bases::Any.new(location: build_location(node))), required: !!node.[](:"block_arg") || node.[](:"yield_arg_count"))
128
127
  else
129
128
  nil
@@ -184,6 +183,7 @@ EMPTY_ARRAY }
184
183
  else
185
184
  nil
186
185
  end)
186
+ name = node.[](:"name")
187
187
  block = (if node.[](:"block")
188
188
  " #{visit_node(node.[](:"block"))}"
189
189
  else
@@ -195,14 +195,21 @@ EMPTY_ARRAY }
195
195
  else
196
196
  nil
197
197
  end)
198
- name = node.[](:"name")
199
198
  call = "#{obj}#{name}#{opening_delimiter}#{args}#{(if has_parens
200
199
  ")"
201
200
  end)}#{block}"
202
201
  case name
203
202
  when "require_relative"
204
203
  (if @on_new_file_referenced
205
- @on_new_file_referenced.call(name, true)
204
+ paths = arg_arr.map() { |a|
205
+ unless a.[](:"type")
206
+ .==("LiteralNode")
207
+ throw(:"error", "Dynamic file paths are not allowed in require_relative")
208
+ end
209
+ eval(visit_node(a, scope)
210
+ .strip)
211
+ }
212
+ @on_new_file_referenced.call(paths, true)
206
213
  end)
207
214
  when "module_function"
208
215
  @after_module_function = true
@@ -254,7 +261,7 @@ case name
254
261
  path = node.[](:"value")
255
262
  src.write_ln("require \"#{path}\"")
256
263
  (if @on_new_file_referenced
257
- @on_new_file_referenced.call(path, false)
264
+ @on_new_file_referenced.call([path], false)
258
265
  end)
259
266
  when "Assign", "OpAssign"
260
267
  src.write_ln("#{visit_node(node.[](:"target"))} #{node.[](:"op")}= #{visit_node(node.[](:"value"))
@@ -608,7 +615,9 @@ EMPTY_HASH }
608
615
  end)
609
616
  # @type var rest_kw: Hash[Symbol, Any]?
610
617
  rest_kw = node.[](:"rest_kw_args")
611
- (if [rp, op, rkw, okw, rest_p, rest_kw].all?() { |a|
618
+ # @type var block_arg: Hash[Symbol, Any]?
619
+ block_arg = node.[](:"block_arg")
620
+ (if [rp, op, rkw, okw, rest_p, rest_kw, block_arg].all?() { |a|
612
621
  a && a.empty? }
613
622
  return nil
614
623
  end)
@@ -626,6 +635,10 @@ a && a.empty? }
626
635
  "**#{visit_node(rest_kw)}"
627
636
  else
628
637
  ""
638
+ end), (if block_arg
639
+ "&#{visit_node(block_arg)}"
640
+ else
641
+ ""
629
642
  end)].reject(&:"empty?")
630
643
  .flatten
631
644
  .join(", ")
@@ -650,6 +663,7 @@ a && a.empty? }
650
663
  :trailing_positionals => EMPTY_ARRAY,
651
664
  :required_keywords => node.[](:"req_kw_args") || EMPTY_HASH,
652
665
  :optional_keywords => node.[](:"opt_kw_args") || EMPTY_HASH,
666
+ :block_arg => true,
653
667
  :rest_keywords => (if node.[](:"rest_kw_args")
654
668
  RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
655
669
  .to_sym, type: RBS::Types::Bases::Any.new(location: build_location(node)))
data/lib/gloss/watcher.rb CHANGED
@@ -1,11 +1,12 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "listen"
7
6
  module Gloss
8
7
  class Watcher
8
+ # @type var @listener: Listen?
9
+ @listener
9
10
  def initialize(paths)
10
11
  @paths = paths
11
12
  (if @paths.empty?
@@ -32,7 +33,7 @@ module Gloss
32
33
  def watch()
33
34
  Gloss.logger
34
35
  .info("Now listening for changes in #{@paths.join(", ")}")
35
- listener = Listen.to(*@paths, latency: 2, only: @only) { |modified, added, removed|
36
+ @listener ||= Listen.to(*@paths, latency: 2, only: @only) { |modified, added, removed|
36
37
  modified.+(added)
37
38
  .each() { |f|
38
39
  Gloss.logger
@@ -64,13 +65,18 @@ nil }
64
65
  }
65
66
  }
66
67
  begin
67
- listener.start
68
+ @listener.start
68
69
  sleep
69
70
  rescue Interrupt
70
- Gloss.logger
71
- .info("Interrupt signal received, shutting down")
72
- exit(0)
71
+ kill
73
72
  end
74
73
  end
74
+ def kill()
75
+ Gloss.logger
76
+ .info("Interrupt signal received, shutting down")
77
+ (if @listener
78
+ @listener.stop
79
+ end)
80
+ end
75
81
  end
76
82
  end