gloss 0.1.1 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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