steep 0.1.0.pre2 → 0.1.0
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 +5 -5
- data/.travis.yml +1 -1
- data/README.md +146 -33
- data/bin/smoke_runner.rb +43 -10
- data/lib/steep/ast/annotation/collection.rb +93 -0
- data/lib/steep/ast/annotation.rb +131 -0
- data/lib/steep/ast/buffer.rb +47 -0
- data/lib/steep/ast/location.rb +82 -0
- data/lib/steep/ast/method_type.rb +116 -0
- data/lib/steep/ast/signature/class.rb +33 -0
- data/lib/steep/ast/signature/const.rb +17 -0
- data/lib/steep/ast/signature/env.rb +123 -0
- data/lib/steep/ast/signature/extension.rb +21 -0
- data/lib/steep/ast/signature/gvar.rb +17 -0
- data/lib/steep/ast/signature/interface.rb +31 -0
- data/lib/steep/ast/signature/members.rb +71 -0
- data/lib/steep/ast/signature/module.rb +21 -0
- data/lib/steep/ast/type_params.rb +13 -0
- data/lib/steep/ast/types/any.rb +39 -0
- data/lib/steep/ast/types/bot.rb +39 -0
- data/lib/steep/ast/types/class.rb +35 -0
- data/lib/steep/ast/types/helper.rb +21 -0
- data/lib/steep/ast/types/instance.rb +39 -0
- data/lib/steep/ast/types/intersection.rb +74 -0
- data/lib/steep/ast/types/name.rb +124 -0
- data/lib/steep/ast/types/self.rb +39 -0
- data/lib/steep/ast/types/top.rb +39 -0
- data/lib/steep/ast/types/union.rb +74 -0
- data/lib/steep/ast/types/var.rb +57 -0
- data/lib/steep/ast/types/void.rb +35 -0
- data/lib/steep/cli.rb +28 -1
- data/lib/steep/drivers/annotations.rb +32 -0
- data/lib/steep/drivers/check.rb +53 -77
- data/lib/steep/drivers/scaffold.rb +303 -0
- data/lib/steep/drivers/utils/each_signature.rb +66 -0
- data/lib/steep/drivers/utils/validator.rb +115 -0
- data/lib/steep/drivers/validate.rb +39 -0
- data/lib/steep/errors.rb +291 -19
- data/lib/steep/interface/abstract.rb +44 -0
- data/lib/steep/interface/builder.rb +470 -0
- data/lib/steep/interface/instantiated.rb +126 -0
- data/lib/steep/interface/ivar_chain.rb +26 -0
- data/lib/steep/interface/method.rb +60 -0
- data/lib/steep/{interface.rb → interface/method_type.rb} +111 -100
- data/lib/steep/interface/substitution.rb +65 -0
- data/lib/steep/module_name.rb +116 -0
- data/lib/steep/parser.rb +1314 -814
- data/lib/steep/parser.y +536 -175
- data/lib/steep/source.rb +220 -25
- data/lib/steep/subtyping/check.rb +673 -0
- data/lib/steep/subtyping/constraints.rb +275 -0
- data/lib/steep/subtyping/relation.rb +41 -0
- data/lib/steep/subtyping/result.rb +126 -0
- data/lib/steep/subtyping/trace.rb +48 -0
- data/lib/steep/subtyping/variable_occurrence.rb +49 -0
- data/lib/steep/subtyping/variable_variance.rb +69 -0
- data/lib/steep/type_construction.rb +1630 -524
- data/lib/steep/type_inference/block_params.rb +100 -0
- data/lib/steep/type_inference/constant_env.rb +55 -0
- data/lib/steep/type_inference/send_args.rb +222 -0
- data/lib/steep/type_inference/type_env.rb +226 -0
- data/lib/steep/type_name.rb +27 -7
- data/lib/steep/typing.rb +4 -0
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +71 -16
- data/smoke/and/a.rb +4 -2
- data/smoke/array/a.rb +4 -5
- data/smoke/array/b.rb +4 -4
- data/smoke/block/a.rb +2 -2
- data/smoke/block/a.rbi +2 -0
- data/smoke/block/b.rb +15 -0
- data/smoke/case/a.rb +3 -3
- data/smoke/class/a.rb +3 -3
- data/smoke/class/b.rb +0 -2
- data/smoke/class/d.rb +2 -2
- data/smoke/class/e.rb +1 -1
- data/smoke/class/f.rb +2 -2
- data/smoke/class/g.rb +8 -0
- data/smoke/const/a.rb +3 -3
- data/smoke/dstr/a.rb +1 -1
- data/smoke/ensure/a.rb +22 -0
- data/smoke/enumerator/a.rb +6 -6
- data/smoke/enumerator/b.rb +22 -0
- data/smoke/extension/a.rb +2 -2
- data/smoke/extension/b.rb +3 -3
- data/smoke/extension/c.rb +1 -1
- data/smoke/hello/hello.rb +2 -2
- data/smoke/if/a.rb +4 -2
- data/smoke/kwbegin/a.rb +8 -0
- data/smoke/literal/a.rb +5 -5
- data/smoke/method/a.rb +5 -5
- data/smoke/method/a.rbi +4 -0
- data/smoke/method/b.rb +29 -0
- data/smoke/module/a.rb +3 -3
- data/smoke/module/a.rbi +9 -0
- data/smoke/module/b.rb +2 -2
- data/smoke/module/c.rb +1 -1
- data/smoke/module/d.rb +5 -0
- data/smoke/module/e.rb +13 -0
- data/smoke/module/f.rb +13 -0
- data/smoke/rescue/a.rb +62 -0
- data/smoke/super/a.rb +2 -2
- data/smoke/type_case/a.rb +35 -0
- data/smoke/yield/a.rb +2 -2
- data/stdlib/builtin.rbi +463 -24
- data/steep.gemspec +3 -2
- metadata +91 -29
- data/lib/steep/annotation.rb +0 -223
- data/lib/steep/signature/class.rb +0 -450
- data/lib/steep/signature/extension.rb +0 -51
- data/lib/steep/signature/interface.rb +0 -49
- data/lib/steep/types/any.rb +0 -31
- data/lib/steep/types/class.rb +0 -27
- data/lib/steep/types/instance.rb +0 -27
- data/lib/steep/types/merge.rb +0 -32
- data/lib/steep/types/name.rb +0 -57
- data/lib/steep/types/union.rb +0 -42
- data/lib/steep/types/var.rb +0 -38
- data/lib/steep/types.rb +0 -4
@@ -0,0 +1,39 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Instance
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location: nil)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Instance)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
self.class.hash
|
17
|
+
end
|
18
|
+
|
19
|
+
alias eql? ==
|
20
|
+
|
21
|
+
def subst(s)
|
22
|
+
s.instance_type or raise "Unexpected substitution: #{inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def free_variables
|
26
|
+
Set.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
"instance"
|
31
|
+
end
|
32
|
+
|
33
|
+
def level
|
34
|
+
[0]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Intersection
|
5
|
+
attr_reader :types
|
6
|
+
attr_reader :location
|
7
|
+
|
8
|
+
def initialize(types:, location: nil)
|
9
|
+
@types = types
|
10
|
+
@location = location
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(types:, location: nil)
|
14
|
+
types.flat_map do |type|
|
15
|
+
if type.is_a?(Intersection)
|
16
|
+
type.types
|
17
|
+
else
|
18
|
+
[type]
|
19
|
+
end
|
20
|
+
end.map do |type|
|
21
|
+
case type
|
22
|
+
when AST::Types::Any
|
23
|
+
return AST::Types::Any.new()
|
24
|
+
when AST::Types::Bot
|
25
|
+
return AST::Types::Bot.new()
|
26
|
+
when AST::Types::Top
|
27
|
+
nil
|
28
|
+
else
|
29
|
+
type
|
30
|
+
end
|
31
|
+
end.compact.uniq.yield_self do |tys|
|
32
|
+
if tys.size == 1
|
33
|
+
tys.first
|
34
|
+
else
|
35
|
+
new(types: tys.sort_by(&:hash), location: location)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
other.is_a?(Intersection) &&
|
42
|
+
other.types == types
|
43
|
+
end
|
44
|
+
|
45
|
+
def hash
|
46
|
+
self.class.hash ^ types.hash
|
47
|
+
end
|
48
|
+
|
49
|
+
alias eql? ==
|
50
|
+
|
51
|
+
def subst(s)
|
52
|
+
self.class.build(location: location,
|
53
|
+
types: types.map {|ty| ty.subst(s) })
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"(#{types.map(&:to_s).sort.join(" & ")})"
|
58
|
+
end
|
59
|
+
|
60
|
+
def free_variables
|
61
|
+
types.each.with_object(Set.new) do |type, set|
|
62
|
+
set.merge(type.free_variables)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
include Helper::ChildrenLevel
|
67
|
+
|
68
|
+
def level
|
69
|
+
[0] + level_of_children(types)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Name
|
5
|
+
attr_reader :location
|
6
|
+
attr_reader :name
|
7
|
+
attr_reader :args
|
8
|
+
|
9
|
+
def initialize(name:, args:, location: nil)
|
10
|
+
@location = location
|
11
|
+
@name = name
|
12
|
+
@args = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
other.is_a?(Name) &&
|
17
|
+
other.name == name &&
|
18
|
+
other.args == args
|
19
|
+
end
|
20
|
+
|
21
|
+
def hash
|
22
|
+
self.class.hash ^ name.hash ^ args.hash
|
23
|
+
end
|
24
|
+
|
25
|
+
alias eql? ==
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
if args.empty?
|
29
|
+
"#{name}"
|
30
|
+
else
|
31
|
+
"#{name}<#{args.join(", ")}>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.new_module(location: nil, name:, args: [])
|
36
|
+
name = ModuleName.parse(name) unless name.is_a?(ModuleName)
|
37
|
+
new(location: location,
|
38
|
+
name: TypeName::Module.new(name: name),
|
39
|
+
args: args)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.new_class(location: nil, name:, constructor:, args: [])
|
43
|
+
name = ModuleName.parse(name) unless name.is_a?(ModuleName)
|
44
|
+
new(location: location,
|
45
|
+
name: TypeName::Class.new(name: name, constructor: constructor),
|
46
|
+
args: args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.new_instance(location: nil, name:, args: [])
|
50
|
+
name = ModuleName.parse(name) unless name.is_a?(ModuleName)
|
51
|
+
new(location: location,
|
52
|
+
name: TypeName::Instance.new(name: name),
|
53
|
+
args: args)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.new_interface(location: nil, name:, args: [])
|
57
|
+
new(location: location, name: TypeName::Interface.new(name: name), args: args)
|
58
|
+
end
|
59
|
+
|
60
|
+
def subst(s)
|
61
|
+
self.class.new(location: location,
|
62
|
+
name: name,
|
63
|
+
args: args.map {|a| a.subst(s) })
|
64
|
+
end
|
65
|
+
|
66
|
+
def instance_type
|
67
|
+
case name
|
68
|
+
when TypeName::Interface, TypeName::Instance
|
69
|
+
self
|
70
|
+
when TypeName::Module, TypeName::Class
|
71
|
+
self.class.new_instance(location: location,
|
72
|
+
name: name.name,
|
73
|
+
args: args)
|
74
|
+
else
|
75
|
+
raise "Unknown name: #{name.inspect}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def class_type(constructor:)
|
80
|
+
case name
|
81
|
+
when TypeName::Instance
|
82
|
+
self.class.new_class(location: location,
|
83
|
+
name: name.name,
|
84
|
+
constructor: constructor,
|
85
|
+
args: [])
|
86
|
+
when TypeName::Class
|
87
|
+
self
|
88
|
+
when TypeName::Module, TypeName::Interface
|
89
|
+
raise "Cannot make class type: #{inspect}"
|
90
|
+
else
|
91
|
+
raise "Unknown name: #{name.inspect}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def module_type
|
96
|
+
case name
|
97
|
+
when TypeName::Instance,
|
98
|
+
self.class.new_module(location: location,
|
99
|
+
name: name.name,
|
100
|
+
args: args)
|
101
|
+
when TypeName::Module
|
102
|
+
self
|
103
|
+
when TypeName::Class, TypeName::Interface
|
104
|
+
raise "Cannot make module type: #{inspect}"
|
105
|
+
else
|
106
|
+
raise "Unknown name: #{name.inspect}"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def free_variables
|
111
|
+
self.args.each.with_object(Set.new) do |type, vars|
|
112
|
+
vars.merge(type.free_variables)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
include Helper::ChildrenLevel
|
117
|
+
|
118
|
+
def level
|
119
|
+
[0] + level_of_children(args)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Self
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location: nil)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
self.class.hash
|
17
|
+
end
|
18
|
+
|
19
|
+
alias eql? ==
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"self"
|
23
|
+
end
|
24
|
+
|
25
|
+
def subst(s)
|
26
|
+
s.self_type or raise "Unexpected substitution: #{inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def free_variables
|
30
|
+
Set.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def level
|
34
|
+
[0]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Top
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location: nil)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Top)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
self.class.hash
|
17
|
+
end
|
18
|
+
|
19
|
+
alias eql? ==
|
20
|
+
|
21
|
+
def subst(s)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"⟙"
|
27
|
+
end
|
28
|
+
|
29
|
+
def free_variables
|
30
|
+
Set.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def level
|
34
|
+
[2]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Union
|
5
|
+
attr_reader :types
|
6
|
+
attr_reader :location
|
7
|
+
|
8
|
+
def initialize(types:, location: nil)
|
9
|
+
@types = types
|
10
|
+
@location = location
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.build(types:, location: nil)
|
14
|
+
types.flat_map do |type|
|
15
|
+
if type.is_a?(Union)
|
16
|
+
type.types
|
17
|
+
else
|
18
|
+
[type]
|
19
|
+
end
|
20
|
+
end.map do |type|
|
21
|
+
case type
|
22
|
+
when AST::Types::Any
|
23
|
+
return AST::Types::Any.new()
|
24
|
+
when AST::Types::Top
|
25
|
+
return AST::Types::Top.new()
|
26
|
+
when AST::Types::Bot
|
27
|
+
nil
|
28
|
+
else
|
29
|
+
type
|
30
|
+
end
|
31
|
+
end.compact.uniq.yield_self do |tys|
|
32
|
+
if tys.length == 1
|
33
|
+
tys.first
|
34
|
+
else
|
35
|
+
new(types: tys.sort_by(&:hash), location: location)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(other)
|
41
|
+
other.is_a?(Union) &&
|
42
|
+
other.types == types
|
43
|
+
end
|
44
|
+
|
45
|
+
def hash
|
46
|
+
self.class.hash ^ types.hash
|
47
|
+
end
|
48
|
+
|
49
|
+
alias eql? ==
|
50
|
+
|
51
|
+
def subst(s)
|
52
|
+
self.class.build(location: location,
|
53
|
+
types: types.map {|ty| ty.subst(s) })
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s
|
57
|
+
"(#{types.map(&:to_s).sort.join(" | ")})"
|
58
|
+
end
|
59
|
+
|
60
|
+
def free_variables
|
61
|
+
types.each.with_object(Set.new) do |type, set|
|
62
|
+
set.merge(type.free_variables)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
include Helper::ChildrenLevel
|
67
|
+
|
68
|
+
def level
|
69
|
+
[0] + level_of_children(types)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Var
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :location
|
7
|
+
|
8
|
+
def initialize(name:, location: nil)
|
9
|
+
@name = name
|
10
|
+
@location = location
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
other.is_a?(Var) &&
|
15
|
+
other.name == name
|
16
|
+
end
|
17
|
+
|
18
|
+
def hash
|
19
|
+
self.class.hash ^ name.hash
|
20
|
+
end
|
21
|
+
|
22
|
+
alias eql? ==
|
23
|
+
|
24
|
+
def self.fresh(name)
|
25
|
+
@mutex ||= Mutex.new
|
26
|
+
|
27
|
+
@mutex.synchronize do
|
28
|
+
@max ||= 0
|
29
|
+
@max += 1
|
30
|
+
|
31
|
+
new(name: :"#{name}(#{@max})")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"'#{name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def subst(s)
|
40
|
+
if s.key?(name)
|
41
|
+
s[name]
|
42
|
+
else
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def free_variables
|
48
|
+
Set.new([name])
|
49
|
+
end
|
50
|
+
|
51
|
+
def level
|
52
|
+
[0]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Steep
|
2
|
+
module AST
|
3
|
+
module Types
|
4
|
+
class Void
|
5
|
+
attr_reader :location
|
6
|
+
|
7
|
+
def initialize(location: nil)
|
8
|
+
@location = location
|
9
|
+
end
|
10
|
+
|
11
|
+
def ==(other)
|
12
|
+
other.is_a?(Void)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hash
|
16
|
+
self.class.hash
|
17
|
+
end
|
18
|
+
|
19
|
+
alias eql? ==
|
20
|
+
|
21
|
+
def subst(s)
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"void"
|
27
|
+
end
|
28
|
+
|
29
|
+
def free_variables
|
30
|
+
Set.new
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/steep/cli.rb
CHANGED
@@ -16,7 +16,7 @@ module Steep
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.available_commands
|
19
|
-
[:check]
|
19
|
+
[:check, :validate, :annotations, :scaffold]
|
20
20
|
end
|
21
21
|
|
22
22
|
def setup_global_options
|
@@ -75,5 +75,32 @@ module Steep
|
|
75
75
|
check.fallback_any_is_error = fallback_any_is_error
|
76
76
|
end.run
|
77
77
|
end
|
78
|
+
|
79
|
+
def process_validate
|
80
|
+
verbose = false
|
81
|
+
|
82
|
+
OptionParser.new do |opts|
|
83
|
+
opts.on("--verbose") { verbose = true }
|
84
|
+
end.parse!(argv)
|
85
|
+
|
86
|
+
signature_dirs = argv.map {|path| Pathname(path) }
|
87
|
+
if signature_dirs.empty?
|
88
|
+
signature_dirs << Pathname(".")
|
89
|
+
end
|
90
|
+
|
91
|
+
Drivers::Validate.new(signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).tap do |validate|
|
92
|
+
validate.verbose = verbose
|
93
|
+
end.run
|
94
|
+
end
|
95
|
+
|
96
|
+
def process_annotations
|
97
|
+
source_paths = argv.map {|file| Pathname(file) }
|
98
|
+
Drivers::Annotations.new(source_paths: source_paths, stdout: stdout, stderr: stderr).run
|
99
|
+
end
|
100
|
+
|
101
|
+
def process_scaffold
|
102
|
+
source_paths = argv.map {|file| Pathname(file) }
|
103
|
+
Drivers::Scaffold.new(source_paths: source_paths, stdout: stdout, stderr: stderr).run
|
104
|
+
end
|
78
105
|
end
|
79
106
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Steep
|
2
|
+
module Drivers
|
3
|
+
class Annotations
|
4
|
+
attr_reader :source_paths
|
5
|
+
attr_reader :stdout
|
6
|
+
attr_reader :stderr
|
7
|
+
attr_reader :labeling
|
8
|
+
|
9
|
+
include Utils::EachSignature
|
10
|
+
|
11
|
+
def initialize(source_paths:, stdout:, stderr:)
|
12
|
+
@source_paths = source_paths
|
13
|
+
@stdout = stdout
|
14
|
+
@stderr = stderr
|
15
|
+
|
16
|
+
@labeling = ASTUtils::Labeling.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
each_ruby_source(source_paths, false) do |source|
|
21
|
+
source.each_annotation.sort_by {|node, _| [node.loc.expression.begin_pos, node.loc.expression.end_pos] }.each do |node, annotations|
|
22
|
+
loc = node.loc
|
23
|
+
stdout.puts "#{source.path}:#{loc.line}:#{loc.column}:#{node.type}:\t#{node.loc.expression.source.lines.first}"
|
24
|
+
annotations.each do |annotation|
|
25
|
+
stdout.puts " #{annotation.location.source}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|