gloss 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gloss/config.rb CHANGED
@@ -8,7 +8,9 @@ require "yaml"
8
8
  module Gloss
9
9
  CONFIG_PATH = ".gloss.yml"
10
10
  Config = OpenStruct.new(default_config: {:frozen_string_literals => true,
11
- :src_dir => "src"}.freeze)
11
+ :src_dir => "src",
12
+ :entrypoint => nil,
13
+ :strict_require => false}.freeze)
12
14
  user_config = (if File.exist?(CONFIG_PATH)
13
15
  YAML.safe_load(File.read(CONFIG_PATH))
14
16
  else
data/lib/gloss/errors.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- module Gloss
6
+ module Gloss
7
7
  module Errors
8
8
  class BaseGlossError < StandardError
9
9
  end
data/lib/gloss/logger.rb CHANGED
@@ -22,13 +22,8 @@ nil => nil,
22
22
  @logger = Logger.new((if real_log_level
23
23
  STDOUT
24
24
  else
25
- nil
25
+ IO::NULL
26
26
  end))
27
- formatter = Logger::Formatter.new
28
- @logger.formatter=(proc() { |severity, datetime, progname, msg|
29
- formatter.call(severity, datetime, progname, msg)
30
- })
31
- @logger
32
27
  end)
33
28
  end
34
29
  end
@@ -0,0 +1,141 @@
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
5
+
6
+ require "rubygems/gem_runner"
7
+ module Gloss
8
+ OUTPUT_BY_PATH = Hash.new
9
+ class ProgLoader
10
+ def initialize()
11
+ entrypoint = Config.entrypoint
12
+ (if entrypoint.==(nil) || entrypoint.==("")
13
+ throw(:"error", "Entrypoint is not yet set in .gloss.yml")
14
+ end)
15
+ @files_to_process = [Utils.absolute_path(Config.entrypoint), Utils.absolute_path(File.join(__dir__ || "", "..", "..", "sig", "core.rbs"))]
16
+ @processed_files = Set.new
17
+ @type_checker = TypeChecker.new
18
+ end
19
+ def run()
20
+ @files_to_process.each() { |path_string|
21
+ unless @processed_files.member?(path_string) || OUTPUT_BY_PATH.[](path_string)
22
+ Gloss.logger
23
+ .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)
28
+ .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)
37
+ .run)
38
+ @processed_files.add(path_string)
39
+ end
40
+ }
41
+ @type_checker
42
+ end
43
+ STDLIB_TYPE_DEPENDENCIES = {"yaml" => ["pstore", "dbm"],
44
+ "rbs" => ["logger", "set", "tsort"],
45
+ "logger" => ["monitor"]}
46
+ private def handle_require(path)
47
+ (if path.start_with?(".")
48
+ base = File.join(Dir.pwd, path)
49
+ fp = base.+(".gl")
50
+ (if File.exist?(fp)
51
+ @files_to_process.<<(fp)
52
+ end)
53
+ return
54
+ end)
55
+ full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
56
+ pathn = Pathname.new(full)
57
+ (if pathn.file?
58
+ @files_to_process.<<(pathn.to_s)
59
+ else
60
+ pathn = Pathname.new("#{File.join(Dir.pwd, "sig", path)}.rbs")
61
+ gem_path = Utils.gem_path_for(path)
62
+ (if gem_path
63
+ sig_files = Dir.glob(File.absolute_path(File.join(gem_path, "..", "..", "sig", "**", "*.rbs")))
64
+ (if sig_files.length
65
+ .positive?
66
+ sig_files.each() { |fp|
67
+ @type_checker.load_sig_path(fp)
68
+ }
69
+ @processed_files.add(path)
70
+ rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { ||
71
+ nil }
72
+ (if rbs_type_deps
73
+ rbs_type_deps.each() { |d|
74
+ handle_require(d)
75
+ }
76
+ end)
77
+ return
78
+ end)
79
+ end)
80
+ (if pathn.file?
81
+ @type_checker.load_sig_path(pathn.to_s)
82
+ @processed_files.add(pathn.to_s)
83
+ else
84
+ rbs_stdlib_dir = File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", path))
85
+ (if Pathname.new(rbs_stdlib_dir)
86
+ .exist?
87
+ load_rbs_from_require_path(path)
88
+ rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { ||
89
+ nil }
90
+ (if rbs_type_deps
91
+ rbs_type_deps.each() { |d|
92
+ load_rbs_from_require_path(d)
93
+ }
94
+ end)
95
+ else
96
+ (if Config.strict_require
97
+ throw(:"error", "Cannot resolve require path for #{path}")
98
+ else
99
+ Gloss.logger
100
+ .debug("No path found for #{path}")
101
+ end)
102
+ end)
103
+ end)
104
+ end)
105
+ end
106
+ private def handle_require_relative(path)
107
+ base = File.join(@filepath, "..", path)
108
+ # @type var pn: String?
109
+ pn = nil
110
+ Gem.suffixes
111
+ .each() { |ext|
112
+ full = File.absolute_path(base.+(ext))
113
+ (if File.exist?(full)
114
+ pn = full
115
+ end)
116
+ }
117
+ (if pn
118
+ unless @files_to_process.include?(pn)
119
+ @files_to_process.<<(pn)
120
+ end
121
+ else
122
+ (if Config.strict_require
123
+ throw(:"error", "Cannot resolve require path for #{pn}")
124
+ else
125
+ Gloss.logger
126
+ .debug("No path found for #{path}")
127
+ end)
128
+ end)
129
+ end
130
+ private def rbs_stdlib_path_for(libr)
131
+ File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "..", "stdlib", libr))
132
+ end
133
+ private def load_rbs_from_require_path(path)
134
+ Dir.glob(File.join(rbs_stdlib_path_for(path), "**", "*.rbs"))
135
+ .each() { |fp|
136
+ @type_checker.load_sig_path(fp)
137
+ @processed_files.add(fp)
138
+ }
139
+ end
140
+ end
141
+ end
data/lib/gloss/scope.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- module Gloss
6
+ module Gloss
7
7
  class Scope < Hash
8
8
  def [](k)
9
9
  fetch(k) { ||
data/lib/gloss/source.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- module Gloss
6
+ module Gloss
7
7
  class Source < String
8
8
  def initialize(indent_level)
9
9
  @indent_level = indent_level
@@ -3,21 +3,29 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- require "pry-byebug"
6
+ require "set"
7
7
  module Gloss
8
8
  class TypeChecker
9
9
  Project = Struct.new(:"targets")
10
- attr_reader(:"steep_target", :"top_level_decls")
10
+ attr_reader(:"steep_target", :"top_level_decls", :"env", :"rbs_gem_dir")
11
11
  def initialize()
12
12
  @steep_target = Steep::Project::Target.new(name: "gloss", options: Steep::Project::Options.new
13
13
  .tap() { |o|
14
14
  o.allow_unknown_constant_assignment=(true)
15
- }, source_patterns: ["gloss.rb"], ignore_patterns: Array.new, signature_patterns: ["sig"])
16
- @top_level_decls = {}
15
+ }, source_patterns: ["**/*.rb"], ignore_patterns: Array.new, signature_patterns: ["sig"])
16
+ @top_level_decls = Set.new
17
+ @rbs_gem_dir = Utils.gem_path_for("rbs")
18
+ env_loader = RBS::EnvironmentLoader.new
19
+ @env = RBS::Environment.from_loader(env_loader)
20
+ project = Steep::Project.new(steepfile_path: Pathname.new(Config.src_dir)
21
+ .realpath)
22
+ project.targets
23
+ .<<(@steep_target)
24
+ loader = Steep::Project::FileLoader.new(project: project)
17
25
  end
18
- def run(rb_str)
26
+ def run(filepath, rb_str)
19
27
  begin
20
- valid_types = check_types(rb_str)
28
+ valid_types = check_types(filepath, rb_str)
21
29
  rescue ParseError => e
22
30
  throw(:"error", "")
23
31
  rescue => e
@@ -34,10 +42,8 @@ case e
34
42
  when Steep::Diagnostic::Ruby::MethodBodyTypeMismatch
35
43
  "Invalid method body type - expected: #{e.expected}, actual: #{e.actual}"
36
44
  when Steep::Diagnostic::Ruby::IncompatibleArguments
37
- "Invalid argmuents - method type: #{e.method_type}\nmethod name: #{e.method_type
38
- .method_decls
39
- .first
40
- .method_name}"
45
+ "Invalid argmuents - method type: #{e.method_types
46
+ .first}\nmethod name: #{e.method_name}"
41
47
  when Steep::Diagnostic::Ruby::ReturnTypeMismatch
42
48
  "Invalid return type - expected: #{e.expected}, actual: #{e.actual}"
43
49
  when Steep::Diagnostic::Ruby::IncompatibleAssignment
@@ -45,7 +51,7 @@ case e
45
51
  when Steep::Diagnostic::Ruby::UnexpectedBlockGiven
46
52
  "Unexpected block given"
47
53
  else
48
- e.inspect
54
+ "#{e.header_line}\n#{e.inspect}"
49
55
  end
50
56
  }
51
57
  .join("\n")
@@ -53,30 +59,36 @@ case e
53
59
  end
54
60
  true
55
61
  end
56
- def check_types(rb_str)
57
- env_loader = RBS::EnvironmentLoader.new
58
- env = RBS::Environment.from_loader(env_loader)
59
- project = Steep::Project.new(steepfile_path: Pathname.new(Config.src_dir)
60
- .realpath)
61
- project.targets
62
- .<<(@steep_target)
63
- loader = Steep::Project::FileLoader.new(project: project)
64
- loader.load_signatures
65
- @steep_target.add_source("gloss.rb", rb_str)
66
- @top_level_decls.each() { |_, decl|
67
- env.<<(decl)
62
+ def ready_for_checking!()
63
+ @top_level_decls.each() { |decl|
64
+ @env.<<(decl)
68
65
  }
69
- env = env.resolve_type_names
70
- @steep_target.instance_variable_set("@environment", env)
66
+ @env = @env.resolve_type_names
67
+ @steep_target.instance_variable_set("@environment", @env)
68
+ end
69
+ def check_types(filepath, rb_str)
70
+ @steep_target.add_source(filepath, rb_str)
71
+ ready_for_checking!
71
72
  @steep_target.type_check
72
73
  (if @steep_target.status
73
74
  .is_a?(Steep::Project::Target::SignatureErrorStatus)
74
75
  throw(:"error", @steep_target.status
75
76
  .errors
76
77
  .map() { |e|
77
- " SignatureSyntaxError:\n Location: #{e.location}\n Message: \"#{e.exception
78
- .error_value
79
- .value}\"" }
78
+ msg = case e
79
+ when Steep::Diagnostic::Signature::UnknownTypeName
80
+ "Unknown type name: #{e.name
81
+ .name} (#{e.location
82
+ .source
83
+ .[](/^.*$/)})"
84
+ when Steep::Diagnostic::Signature::InvalidTypeApplication
85
+ "Invalid type application: #{e.header_line}"
86
+ when Steep::Diagnostic::Signature::DuplicatedMethodDefinition
87
+ "Duplicated method: #{e.header_line}"
88
+ else
89
+ e.header_line
90
+ end
91
+ " SignatureSyntaxError:\n Location: #{e.location}\n Message: \"#{msg}\"" }
80
92
  .join("\n"))
81
93
  end)
82
94
  @steep_target.source_files
@@ -92,5 +104,11 @@ true
92
104
  .is_a?(Steep::Project::Target::TypeCheckStatus) && @steep_target.no_error? && @steep_target.errors
93
105
  .empty?
94
106
  end
107
+ def load_sig_path(path)
108
+ Gloss.logger
109
+ .debug("Loading signature file for #{path}")
110
+ @steep_target.add_signature(path, File.open(path)
111
+ .read)
112
+ end
95
113
  end
96
114
  end
@@ -0,0 +1,44 @@
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
5
+
6
+ require "rubygems"
7
+ module Gloss
8
+ module Utils
9
+ module_function
10
+ def absolute_path(path)
11
+ pn = Pathname.new(path)
12
+ (if pn.absolute?
13
+ pn.to_s
14
+ else
15
+ ap = File.absolute_path(path)
16
+ (if File.exist?(ap)
17
+ ap
18
+ else
19
+ throw(:"error", "File path #{path} does not exist (also looked for #{ap})")
20
+ end)
21
+ end)
22
+ end
23
+ 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
35
+ end
36
+ def with_file_header(str)
37
+ "#{Visitor::FILE_HEADER}\n\n#{str}"
38
+ end
39
+ def src_path_to_output_path(src_path)
40
+ src_path.sub("#{Config.src_dir}/", "")
41
+ .sub(/\.gl$/, ".rb")
42
+ end
43
+ end
44
+ end
data/lib/gloss/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  ##### See src/ to make changes
5
5
 
6
6
  module Gloss
7
- VERSION = "0.0.6"
7
+ VERSION = "0.1.0"
8
8
  end
@@ -4,29 +4,24 @@
4
4
  ##### See src/ to make changes
5
5
 
6
6
  module Gloss
7
- module Utils
8
- module_function
9
- def with_file_header(str)
10
- "#{Builder::FILE_HEADER}\n\n#{str}"
11
- end
12
- end
13
- class Builder
7
+ class Visitor
14
8
  FILE_HEADER = " #{(if Config.frozen_string_literals
15
9
  "# frozen_string_literal: true\n"
16
10
  end)}\n ##### This file was generated by Gloss; any changes made here will be overwritten.\n ##### See #{Config.src_dir}/ to make changes"
17
- include Utils
18
11
  attr_reader(:"tree")
19
- def initialize(tree_hash, type_checker = nil)
12
+ def initialize(tree_hash, type_checker = nil, on_new_file_referenced = nil)
13
+ @on_new_file_referenced = on_new_file_referenced
20
14
  @indent_level = 0
21
15
  @inside_macro = false
22
16
  @eval_vars = false
23
17
  @current_scope = nil
24
18
  @tree = tree_hash
25
19
  @type_checker = type_checker
20
+ @after_module_function = false
26
21
  end
27
22
  def run()
28
23
  rb_output = visit_node(@tree)
29
- with_file_header(rb_output)
24
+ Utils.with_file_header(rb_output)
30
25
  end
31
26
  def visit_node(node, scope = Scope.new)
32
27
  src = Source.new(@indent_level)
@@ -40,21 +35,30 @@ case node.[](:"type")
40
35
  RBS::Namespace.root
41
36
  end)
42
37
  superclass_type = nil
43
- superclass_output = nil
38
+ superclass_output = ""
44
39
  (if node.[](:"superclass")
45
40
  @eval_vars = true
46
41
  superclass_output = visit_node(node.[](:"superclass"))
47
42
  @eval_vars = false
48
- superclass_type = RBS::Parser.parse_type(superclass_output)
43
+ args = Array.new
49
44
  (if node.dig(:"superclass", :"type")
50
45
  .==("Generic")
51
- superclass_output = superclass_output.[](/^[^\[]+/)
46
+ superclass_output = superclass_output.[](/^[^\[]+/) || superclass_output
47
+ args = node.dig(:"superclass", :"args")
48
+ .map() { |n|
49
+ RBS::Parser.parse_type(visit_node(n))
50
+ }
52
51
  end)
52
+ class_name_index = superclass_output.index(/[^(?:::)]+\z/) || 0
53
+ namespace = superclass_output.[](0, class_name_index)
54
+ superclass_name = superclass_output.[](/[^(?:::)]+\z/) || superclass_output
55
+ superclass_type = RBS::AST::Declarations::Class::Super.new(name: RBS::TypeName.new(namespace: method(:"Namespace")
56
+ .call(namespace), name: superclass_name.to_sym), args: args, location: build_location(node))
53
57
  end)
54
- src.write_ln("class #{class_name}#{(if superclass_output
58
+ src.write_ln("class #{class_name}#{unless superclass_output.blank?
55
59
  " < #{superclass_output}"
56
- end)}")
57
- class_type = RBS::AST::Declarations::Class.new(name: RBS::TypeName.new(namespace: current_namespace, name: class_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, super_class: superclass_type, members: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
60
+ end}")
61
+ class_type = RBS::AST::Declarations::Class.new(name: RBS::TypeName.new(namespace: current_namespace, name: class_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, super_class: superclass_type, members: Array.new, annotations: Array.new, location: build_location(node), comment: node.[](:"comment"))
58
62
  old_parent_scope = @current_scope
59
63
  @current_scope = class_type
60
64
  indented(src) { ||
@@ -68,14 +72,13 @@ case node.[](:"type")
68
72
  @current_scope.members
69
73
  .<<(class_type)
70
74
  end)
71
- (if @type_checker
72
- unless @current_scope
73
- @type_checker.top_level_decls
74
- .[]=(class_type.name
75
- .name, class_type)
76
- end
75
+ (if @type_checker && !@current_scope
76
+ @type_checker.top_level_decls
77
+ .add(class_type)
77
78
  end)
78
79
  when "ModuleNode"
80
+ existing_module_function_state = @after_module_function.dup
81
+ @after_module_function = false
79
82
  module_name = visit_node(node.[](:"name"))
80
83
  src.write_ln("module #{module_name}")
81
84
  current_namespace = (if @current_scope
@@ -84,7 +87,7 @@ case node.[](:"type")
84
87
  else
85
88
  RBS::Namespace.root
86
89
  end)
87
- module_type = RBS::AST::Declarations::Module.new(name: RBS::TypeName.new(namespace: current_namespace, name: module_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, self_types: Array.new, members: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
90
+ module_type = RBS::AST::Declarations::Module.new(name: RBS::TypeName.new(namespace: current_namespace, name: module_name.to_sym), type_params: RBS::AST::Declarations::ModuleTypeParams.new, self_types: Array.new, members: Array.new, annotations: Array.new, location: build_location(node), comment: node.[](:"comment"))
88
91
  old_parent_scope = @current_scope
89
92
  @current_scope = module_type
90
93
  indented(src) { ||
@@ -97,14 +100,12 @@ case node.[](:"type")
97
100
  @current_scope.members
98
101
  .<<(module_type)
99
102
  end)
100
- (if @type_checker
101
- unless @current_scope
102
- @type_checker.top_level_decls
103
- .[]=(module_type.name
104
- .name, module_type)
105
- end
103
+ (if @type_checker && !@current_scope
104
+ @type_checker.top_level_decls
105
+ .add(module_type)
106
106
  end)
107
107
  src.write_ln("end")
108
+ @after_module_function = existing_module_function_state
108
109
  when "DefNode"
109
110
  args = render_args(node)
110
111
  receiver = (if node.[](:"receiver")
@@ -118,21 +119,25 @@ case node.[](:"type")
118
119
  return_type = (if node.[](:"return_type")
119
120
  RBS::Types::ClassInstance.new(name: RBS::TypeName.new(name: eval(visit_node(node.[](:"return_type")))
120
121
  .to_s
121
- .to_sym, namespace: RBS::Namespace.root), args: EMPTY_ARRAY, location: node.[](:"location"))
122
+ .to_sym, namespace: RBS::Namespace.root), args: EMPTY_ARRAY, location: build_location(node))
122
123
  else
123
- RBS::Types::Bases::Any.new(location: node.[](:"location"))
124
+ RBS::Types::Bases::Any.new(location: build_location(node))
124
125
  end)
125
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")
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: node.[](:"location"))), required: !!node.[](:"block_arg") || node.[](:"yield_arg_count"))
127
+ 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"))
127
128
  else
128
129
  nil
129
- end), location: node.[](:"location"))]
130
+ end), location: build_location(node))]
130
131
  method_definition = RBS::AST::Members::MethodDefinition.new(name: node.[](:"name")
131
- .to_sym, kind: (if receiver
132
- :"class"
132
+ .to_sym, kind: (if @after_module_function
133
+ :"singleton_instance"
133
134
  else
134
- :"instance"
135
- end), types: method_types, annotations: EMPTY_ARRAY, location: node.[](:"location"), comment: node.[](:"comment"), overload: false)
135
+ (if receiver
136
+ :"singleton"
137
+ else
138
+ :"instance"
139
+ end)
140
+ end), types: method_types, annotations: EMPTY_ARRAY, location: build_location(node), comment: node.[](:"comment"), overload: false)
136
141
  (if @current_scope
137
142
  @current_scope.members
138
143
  .<<(method_definition)
@@ -190,9 +195,18 @@ EMPTY_ARRAY }
190
195
  else
191
196
  nil
192
197
  end)
193
- call = "#{obj}#{node.[](:"name")}#{opening_delimiter}#{args}#{(if has_parens
198
+ name = node.[](:"name")
199
+ call = "#{obj}#{name}#{opening_delimiter}#{args}#{(if has_parens
194
200
  ")"
195
201
  end)}#{block}"
202
+ case name
203
+ when "require_relative"
204
+ (if @on_new_file_referenced
205
+ @on_new_file_referenced.call(name, true)
206
+ end)
207
+ when "module_function"
208
+ @after_module_function = true
209
+ end
196
210
  src.write_ln(call)
197
211
  when "Block"
198
212
  args = render_args(node)
@@ -237,7 +251,11 @@ EMPTY_ARRAY }
237
251
  when "Path"
238
252
  src.write(node.[](:"value"))
239
253
  when "Require"
240
- src.write_ln("require \"#{node.[](:"value")}\"")
254
+ path = node.[](:"value")
255
+ src.write_ln("require \"#{path}\"")
256
+ (if @on_new_file_referenced
257
+ @on_new_file_referenced.call(path, false)
258
+ end)
241
259
  when "Assign", "OpAssign"
242
260
  src.write_ln("#{visit_node(node.[](:"target"))} #{node.[](:"op")}= #{visit_node(node.[](:"value"))
243
261
  .strip}")
@@ -426,7 +444,12 @@ EMPTY_ARRAY }
426
444
  src.write("return#{val}")
427
445
  when "TypeDeclaration"
428
446
  src.write_ln("# @type var #{visit_node(node.[](:"var"))}: #{visit_node(node.[](:"declared_type"))}")
429
- src.write_ln("#{visit_node(node.[](:"var"))} = #{visit_node(node.[](:"value"))}")
447
+ value = (if node.[](:"value")
448
+ " = #{visit_node(node.[](:"value"))}"
449
+ else
450
+ nil
451
+ end)
452
+ src.write_ln("#{visit_node(node.[](:"var"))}#{value}")
430
453
  when "ExceptionHandler"
431
454
  src.write_ln("begin")
432
455
  indented(src) { ||
@@ -483,7 +506,7 @@ EMPTY_ARRAY }
483
506
  name = visit_node(node.[](:"name"))
484
507
  src.write_ln("include #{name}")
485
508
  type = RBS::AST::Members::Include.new(name: method(:"TypeName")
486
- .call(name), args: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
509
+ .call(name), args: Array.new, annotations: Array.new, location: build_location(node), comment: node.[](:"comment"))
487
510
  (if @current_scope
488
511
  @current_scope.members
489
512
  .<<(type)
@@ -501,7 +524,7 @@ EMPTY_ARRAY }
501
524
  name = visit_node(node.[](:"name"))
502
525
  src.write_ln("extend #{name}")
503
526
  type = RBS::AST::Members::Extend.new(name: method(:"TypeName")
504
- .call(name), args: Array.new, annotations: Array.new, location: node.[](:"location"), comment: node.[](:"comment"))
527
+ .call(name), args: Array.new, annotations: Array.new, location: build_location(node), comment: node.[](:"comment"))
505
528
  (if @current_scope
506
529
  @current_scope.members
507
530
  .<<(type)
@@ -607,34 +630,38 @@ a && a.empty? }
607
630
  .flatten
608
631
  .join(", ")
609
632
  representation = "(#{contents})"
610
- rp.map!() { |a|
633
+ rp_args = rp.map() { |a|
611
634
  RBS::Types::Function::Param.new(name: visit_node(a)
612
- .to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
635
+ .to_sym, type: RBS::Types::Bases::Any.new(location: build_location(a)))
613
636
  }
614
- op.map!() { |a|
637
+ op_args = op.map() { |a|
615
638
  RBS::Types::Function::Param.new(name: visit_node(a)
616
- .to_sym, type: RBS::Types::Bases::Any.new(location: a.[](:"location")))
639
+ .to_sym, type: RBS::Types::Bases::Any.new(location: build_location(a)))
617
640
  }
618
- rest_p = (if rpa = node.[](:"rest_p_args")
619
- RBS::Types::Function::Param.new(name: visit_node(rpa)
620
- .to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
641
+ rpa = (if rest_p
642
+ RBS::Types::Function::Param.new(name: rest_p.to_sym, type: RBS::Types::Bases::Any.new(location: build_location(node)))
621
643
  else
622
644
  nil
623
645
  end)
624
646
  {:representation => representation,
625
- :types => {:required_positionals => rp,
626
- :optional_positionals => op,
627
- :rest_positionals => rest_p,
647
+ :types => {:required_positionals => rp_args,
648
+ :optional_positionals => op_args,
649
+ :rest_positionals => rpa,
628
650
  :trailing_positionals => EMPTY_ARRAY,
629
651
  :required_keywords => node.[](:"req_kw_args") || EMPTY_HASH,
630
652
  :optional_keywords => node.[](:"opt_kw_args") || EMPTY_HASH,
631
653
  :rest_keywords => (if node.[](:"rest_kw_args")
632
654
  RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
633
- .to_sym, type: RBS::Types::Bases::Any.new(location: node.[](:"location")))
655
+ .to_sym, type: RBS::Types::Bases::Any.new(location: build_location(node)))
634
656
  else
635
657
  nil
636
658
  end)
637
659
  }.freeze}.freeze
638
660
  end
661
+ def build_location(node)
662
+ unless node.[](:"location")
663
+ return nil
664
+ end
665
+ end
639
666
  end
640
667
  end