visualize_packwerk 0.0.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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +32 -0
  3. data/lib/visualize_packwerk/graph_interface.rb +17 -0
  4. data/lib/visualize_packwerk/node_interface.rb +29 -0
  5. data/lib/visualize_packwerk/package_graph.rb +48 -0
  6. data/lib/visualize_packwerk/package_node.rb +28 -0
  7. data/lib/visualize_packwerk/package_relationships.rb +158 -0
  8. data/lib/visualize_packwerk/railtie.rb +15 -0
  9. data/lib/visualize_packwerk/tasks/visualize_packwerk.rake +73 -0
  10. data/lib/visualize_packwerk/team_graph.rb +52 -0
  11. data/lib/visualize_packwerk/team_node.rb +27 -0
  12. data/lib/visualize_packwerk.rb +17 -0
  13. data/sorbet/config +2 -0
  14. data/sorbet/rbi/gems/activesupport@7.0.3.1.rbi +76 -0
  15. data/sorbet/rbi/gems/ast@2.4.2.rbi +522 -0
  16. data/sorbet/rbi/gems/code_ownership@1.28.0.rbi +411 -0
  17. data/sorbet/rbi/gems/code_teams@1.0.0.rbi +138 -0
  18. data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
  19. data/sorbet/rbi/gems/concurrent-ruby@1.1.10.rbi +8 -0
  20. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +866 -0
  21. data/sorbet/rbi/gems/i18n@1.12.0.rbi +8 -0
  22. data/sorbet/rbi/gems/json@2.6.2.rbi +1423 -0
  23. data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
  24. data/sorbet/rbi/gems/minitest@5.16.2.rbi +9 -0
  25. data/sorbet/rbi/gems/package_protections@1.3.0.rbi +654 -0
  26. data/sorbet/rbi/gems/parallel@1.22.1.rbi +163 -0
  27. data/sorbet/rbi/gems/parse_packwerk@0.11.0.rbi +148 -0
  28. data/sorbet/rbi/gems/parser@3.1.2.0.rbi +4261 -0
  29. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  30. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +8 -0
  31. data/sorbet/rbi/gems/rake@13.0.6.rbi +1854 -0
  32. data/sorbet/rbi/gems/rbi@0.0.15.rbi +2340 -0
  33. data/sorbet/rbi/gems/regexp_parser@2.5.0.rbi +8 -0
  34. data/sorbet/rbi/gems/rexml@3.2.5.rbi +8 -0
  35. data/sorbet/rbi/gems/rspec-core@3.11.0.rbi +7698 -0
  36. data/sorbet/rbi/gems/rspec-expectations@3.11.0.rbi +6201 -0
  37. data/sorbet/rbi/gems/rspec-mocks@3.11.1.rbi +3625 -0
  38. data/sorbet/rbi/gems/rspec-support@3.11.0.rbi +1176 -0
  39. data/sorbet/rbi/gems/rspec@3.11.0.rbi +40 -0
  40. data/sorbet/rbi/gems/rubocop-ast@1.19.1.rbi +8 -0
  41. data/sorbet/rbi/gems/rubocop-sorbet@0.6.11.rbi +8 -0
  42. data/sorbet/rbi/gems/rubocop@1.33.0.rbi +8 -0
  43. data/sorbet/rbi/gems/ruby-graphviz@1.2.5.rbi +840 -0
  44. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +8 -0
  45. data/sorbet/rbi/gems/spoom@1.1.11.rbi +1600 -0
  46. data/sorbet/rbi/gems/tapioca@0.8.3.rbi +1978 -0
  47. data/sorbet/rbi/gems/thor@1.2.1.rbi +2921 -0
  48. data/sorbet/rbi/gems/tzinfo@2.0.5.rbi +8 -0
  49. data/sorbet/rbi/gems/unicode-display_width@2.2.0.rbi +8 -0
  50. data/sorbet/rbi/gems/unparser@0.6.5.rbi +8 -0
  51. data/sorbet/rbi/gems/webrick@1.7.0.rbi +1802 -0
  52. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +288 -0
  53. data/sorbet/rbi/gems/yard@0.9.28.rbi +12863 -0
  54. data/sorbet/tapioca/config.yml +13 -0
  55. data/sorbet/tapioca/require.rb +7 -0
  56. metadata +241 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e70be5b42437ab3ffacbbff1a3ec57c1116b8bc5fd1e4fc91163631414a35dae
4
+ data.tar.gz: 7cc7f753055f8f655d0787f3452f3b600eef10182689d637ac2a49eaf96706ff
5
+ SHA512:
6
+ metadata.gz: fe981d2228c1b9039020e5b715cb578b3c5a5a8f6bbade61513151d1a770d06eb327463563b96468e00e0359e7aa6fcadf991d10f03ddec1e923396266c008c0
7
+ data.tar.gz: 8de59866b806300164ccd476d9e481b7aba1ff328d746c246aec49fe3d65c353511dc2db8713807787b1e991c6fcf8040281fee7ff03766c821111950373b1c2
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # visualize_packwerk
2
+
3
+ This pack contains rake tasks to help visualize relationships between packwerk packs.
4
+
5
+ # Usage
6
+ ## Building a package graph for a selection of packages (owned by 5 teams max)
7
+ ```
8
+ bin/rails visualize_packwerk:package_relationships['packs/pack1','packs/pack2']
9
+ ```
10
+
11
+ # Building a package graph for specific teams (5 teams max)
12
+ ```
13
+ bin/rails visualize_packwerk:package_relationships_for_teams['Team1','Team2']
14
+ ```
15
+
16
+ # Building a package graph for all packages (this is slow and produces a huge file)
17
+ ```
18
+ bin/rails visualize_packwerk:package_relationships
19
+ ```
20
+
21
+ # Building a TEAM graph for specific teams
22
+ ```
23
+ bin/rails visualize_packwerk:team_relationships['Team1','Team2']
24
+ ```
25
+
26
+ # Building a TEAM graph for all teams (this is slow and produces a huge file)
27
+ ```
28
+ bin/rails visualize_packwerk:team_relationships
29
+ ```
30
+
31
+ # Want to change something or add a feature?
32
+ Submit a PR or post an issue!
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ # This stores graphviz-independent views of our package graph.
5
+ # It should be optimized for fast lookup (leveraging internal indexes, which are stable due to the immutability of the package nodes)
6
+ # A `TeamGraph` should be able to consume this and basically just create a reduced version
7
+ # Lastly, each one should implement a common interface, and graphviz should use that interface and take in either types of graph via the interface
8
+ module GraphInterface
9
+ extend T::Sig
10
+ extend T::Helpers
11
+ interface!
12
+
13
+ sig { abstract.returns(T::Set[NodeInterface]) }
14
+ def nodes
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,29 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ module NodeInterface
5
+ extend T::Sig
6
+ extend T::Helpers
7
+ interface!
8
+
9
+ sig { abstract.returns(String) }
10
+ def name
11
+ end
12
+
13
+ sig { abstract.returns(String) }
14
+ def group_name
15
+ end
16
+
17
+ sig { abstract.returns(T::Hash[String, Integer]) }
18
+ def violations_by_node_name
19
+ end
20
+
21
+ sig { abstract.returns(T::Array[String]) }
22
+ def dependencies
23
+ end
24
+
25
+ sig { abstract.params(node_name: String).returns(T::Boolean) }
26
+ def depends_on?(node_name)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,48 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ class PackageGraph
5
+ extend T::Sig
6
+ include GraphInterface
7
+
8
+ sig { returns(T::Set[PackageNode]) }
9
+ attr_reader :package_nodes
10
+
11
+ sig { override.returns(T::Set[NodeInterface]) }
12
+ def nodes
13
+ package_nodes
14
+ end
15
+
16
+ sig { params(package_nodes: T::Set[PackageNode]).void }
17
+ def initialize(package_nodes:)
18
+ @package_nodes = package_nodes
19
+ @index_by_name = T.let({}, T::Hash[String, PackageNode])
20
+ end
21
+
22
+ sig { returns(PackageGraph) }
23
+ def self.construct
24
+ package_nodes = Set.new
25
+ ParsePackwerk.all.each do |p|
26
+ # We could consider ignoring the root!
27
+ # We would also need to ignore it when parsing PackageNodes.
28
+ # next if p.name == ParsePackwerk::ROOT_PACKAGE_NAME
29
+ owner = CodeOwnership.for_package(p)
30
+ violations_by_package = PackageProtections::ProtectedPackage.from(p).violations.group_by(&:to_package_name).transform_values(&:count)
31
+
32
+ package_nodes << PackageNode.new(
33
+ name: p.name,
34
+ team_name: owner&.name || 'Unknown',
35
+ violations_by_package: violations_by_package,
36
+ dependencies: Set.new(p.dependencies)
37
+ )
38
+ end
39
+
40
+ PackageGraph.new(package_nodes: package_nodes)
41
+ end
42
+
43
+ sig { params(name: String).returns(PackageNode) }
44
+ def package_by_name(name)
45
+ @index_by_name[name] ||= T.must(package_nodes.find { |node| node.name == name })
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,28 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ class PackageNode < T::Struct
5
+ extend T::Sig
6
+ include NodeInterface
7
+
8
+ const :name, String
9
+ const :team_name, String
10
+ const :violations_by_package, T::Hash[String, Integer]
11
+ const :dependencies, T::Set[String]
12
+
13
+ sig { override.returns(T::Hash[String, Integer]) }
14
+ def violations_by_node_name
15
+ violations_by_package
16
+ end
17
+
18
+ sig { override.returns(String) }
19
+ def group_name
20
+ team_name
21
+ end
22
+
23
+ sig { override.params(node_name: String).returns(T::Boolean) }
24
+ def depends_on?(node_name)
25
+ dependencies.include?(node_name) || (violations_by_package[node_name] || 0) > 0
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,158 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ class PackageRelationships
5
+ extend T::Sig
6
+
7
+ OUTPUT_FILENAME = T.let('packwerk.png'.freeze, String)
8
+
9
+ sig { void }
10
+ def initialize
11
+ @colors_by_team = T.let({}, T::Hash[String, String])
12
+ @remaining_colors = T.let(
13
+ [
14
+ # Found using https://htmlcolorcodes.com/color-picker/
15
+ '#77EE77', # green
16
+ '#DFEE77', # yellow
17
+ '#77EEE6', # teal
18
+ '#EEC077', # orange
19
+ '#EE77BF', # pink
20
+ '#EE6F6F', # red
21
+ '#ED6EDE', # magenta
22
+ '#8E8CFE', # blue
23
+ '#EEA877', # red-orange
24
+ ], T::Array[String]
25
+ )
26
+ end
27
+
28
+ sig { params(teams: T::Array[CodeTeams::Team]).void }
29
+ def create_package_graph_for_teams!(teams)
30
+ packages = ParsePackwerk.all.select do |package|
31
+ teams.map(&:name).include?(CodeOwnership.for_package(package)&.name)
32
+ end
33
+
34
+ create_package_graph!(packages)
35
+ end
36
+
37
+ sig { params(teams: T::Array[CodeTeams::Team], show_all_teams: T::Boolean).void }
38
+ def create_team_graph!(teams, show_all_teams: false)
39
+ package_graph = PackageGraph.construct
40
+ team_graph = TeamGraph.from_package_graph(package_graph)
41
+ highlighted_node_names = teams.map(&:name)
42
+
43
+ draw_graph!(team_graph, highlighted_node_names, show_all_nodes: show_all_teams)
44
+ end
45
+
46
+ sig { params(packages: T::Array[ParsePackwerk::Package], show_all_packs: T::Boolean).void }
47
+ def create_package_graph!(packages, show_all_packs: false)
48
+ graph = PackageGraph.construct
49
+ highlighted_node_names = packages.map(&:name)
50
+ draw_graph!(graph, highlighted_node_names, show_all_nodes: show_all_packs)
51
+ end
52
+
53
+ sig { params(packages: T::Array[ParsePackwerk::Package], show_all_nodes: T::Boolean).void }
54
+ def create_graph!(packages, show_all_nodes: false)
55
+ graph = PackageGraph.construct
56
+ highlighted_node_names = packages.map(&:name)
57
+ draw_graph!(graph, highlighted_node_names, show_all_nodes: show_all_nodes)
58
+ end
59
+
60
+ sig { params(graph: GraphInterface, highlighted_node_names: T::Array[String], show_all_nodes: T::Boolean).void }
61
+ def draw_graph!(graph, highlighted_node_names, show_all_nodes: false)
62
+ # SFDP looks better than dot in some cases, but less good in other cases.
63
+ # If your visualization looks bad, change the layout to other_layout!
64
+ # https://graphviz.org/docs/layouts/
65
+ default_layout = :dot
66
+ # other_layout = :sfdp
67
+ graphviz_graph = GraphViz.new(:G, type: :digraph, dpi: 100, layout: default_layout)
68
+
69
+ # Create graph nodes
70
+ graphviz_nodes = T.let({}, T::Hash[String, GraphViz::Node])
71
+
72
+ nodes_to_draw = graph.nodes
73
+
74
+ nodes_to_draw.each do |node|
75
+ next unless highlighted_node_names.any? { |highlighted_node_name| node.depends_on?(highlighted_node_name) } || highlighted_node_names.include?(node.name)
76
+
77
+ highlight_node = highlighted_node_names.include?(node.name) && !show_all_nodes
78
+ graphviz_nodes[node.name] = add_node(node, graphviz_graph, highlight_node)
79
+ end
80
+
81
+ max_edge_width = 10
82
+
83
+ # Draw all edges
84
+ nodes_to_draw.each do |node|
85
+ node.dependencies.each do |to_node|
86
+ next unless highlighted_node_names.include?(to_node)
87
+
88
+ graphviz_graph.add_edges(
89
+ graphviz_nodes[node.name],
90
+ graphviz_nodes[to_node],
91
+ { color: 'darkgreen' }
92
+ )
93
+ end
94
+
95
+ node.violations_by_node_name.each do |to_node_name, violation_count|
96
+ next unless highlighted_node_names.include?(to_node_name)
97
+
98
+ edge_width = [
99
+ [(violation_count / 5).to_i, 1].max, # rubocop:disable Lint/NumberConversion
100
+ max_edge_width,
101
+ ].min
102
+
103
+ graphviz_graph.add_edges(
104
+ graphviz_nodes[node.name],
105
+ graphviz_nodes[to_node_name],
106
+ { color: 'red', penwidth: edge_width }
107
+ )
108
+ end
109
+ end
110
+
111
+ # Save graph to filesystem
112
+ puts "Outputting to: #{OUTPUT_FILENAME}"
113
+ graphviz_graph.output(png: OUTPUT_FILENAME)
114
+ puts 'Finished!'
115
+ end
116
+
117
+ sig { params(node: NodeInterface, graph: GraphViz, highlight_node: T::Boolean).returns(GraphViz::Node) }
118
+ def add_node(node, graph, highlight_node)
119
+ default_node_options = {
120
+ fontsize: 26.0,
121
+ fontcolor: 'white',
122
+ fillcolor: 'black',
123
+ color: 'black',
124
+ height: 1.0,
125
+ style: 'filled, rounded',
126
+ shape: 'box',
127
+ }
128
+
129
+ node_options = if highlight_node
130
+ default_node_options.merge(
131
+ fillcolor: highlight_by_group(node),
132
+ color: highlight_by_group(node),
133
+ fontcolor: 'black'
134
+ )
135
+ else
136
+ default_node_options
137
+ end
138
+
139
+ graph.add_nodes(node.name, **node_options)
140
+ end
141
+
142
+ sig { params(node: NodeInterface).returns(String) }
143
+ def highlight_by_group(node)
144
+ highlighted_package_color = @colors_by_team[node.group_name]
145
+ if !highlighted_package_color
146
+ highlighted_package_color = @remaining_colors.first
147
+ raise 'Can only color nodes a max of 5 unique colors for now' if highlighted_package_color.nil?
148
+
149
+ @remaining_colors.delete(highlighted_package_color)
150
+ @colors_by_team[node.group_name] = highlighted_package_color
151
+ end
152
+
153
+ highlighted_package_color
154
+ end
155
+ end
156
+
157
+ private_constant :PackageRelationships
158
+ end
@@ -0,0 +1,15 @@
1
+ # typed: ignore
2
+
3
+ require 'visualize_packwerk'
4
+ require 'rails'
5
+
6
+ module VisualizePackwerk
7
+ class Railtie < Rails::Railtie
8
+ railtie_name :visualize_packwerk
9
+
10
+ rake_tasks do
11
+ path = File.expand_path(__dir__)
12
+ Dir.glob("#{path}/tasks/visualize_packwerk.rake").each { |f| load f }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,73 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ class TaskLoader
5
+ include Rake::DSL
6
+ extend T::Sig
7
+
8
+ sig { void }
9
+ def create_tasks!
10
+ namespace(:visualize_packwerk) do
11
+ # This creates the array of symbols that are needed to declare an argument to a rake task
12
+ package_args = (1..100).map { |i| "package#{i}".to_sym }
13
+
14
+ desc('Graph packages')
15
+ task(:package_relationships, package_args => :environment) do |_task, args|
16
+ show_all_packs = args.to_hash.values.none?
17
+ packages = if show_all_packs
18
+ ParsePackwerk.all
19
+ else
20
+ args.to_hash.values.map do |pack_name|
21
+ found_package = ParsePackwerk.all.find { |p| p.name == pack_name }
22
+ if found_package.nil?
23
+ abort "Could not find pack with name: #{pack_name}"
24
+ end
25
+
26
+ found_package
27
+ end
28
+ end
29
+
30
+ PackageRelationships.new.create_package_graph!(packages, show_all_packs: show_all_packs)
31
+ end
32
+
33
+ # This creates the array of symbols that are needed to declare an argument to a rake task
34
+ team_args = (1..5).map { |i| "team#{i}".to_sym }
35
+
36
+ desc('Graph packages for teams')
37
+ task(:package_relationships_for_teams, team_args => :environment) do |_task, args|
38
+ teams = args.to_hash.values.map do |team_name|
39
+ team = CodeTeams.find(team_name)
40
+ if team.nil?
41
+ abort("Could not find team with name: #{team_name}. Check your config/teams/subdirectory/team.yml for correct team spelling, e.g. `Product Infrastructure`")
42
+ end
43
+
44
+ team
45
+ end
46
+
47
+ PackageRelationships.new.create_package_graph_for_teams!(teams)
48
+ end
49
+
50
+ desc('Graph team relationships')
51
+ task(:team_relationships, team_args => :environment) do |_task, args|
52
+ show_all_teams = args.to_hash.values.none?
53
+ teams = if show_all_teams
54
+ CodeTeams.all
55
+ else
56
+ args.to_hash.values.map do |team_name|
57
+ team = CodeTeams.find(team_name)
58
+ if team.nil?
59
+ abort("Could not find team with name: #{team_name}. Check your config/teams/subdirectory/team.yml for correct team spelling, e.g. `Product Infrastructure`")
60
+ end
61
+
62
+ team
63
+ end
64
+ end
65
+
66
+ PackageRelationships.new.create_team_graph!(teams, show_all_teams: show_all_teams)
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ VisualizePackwerk::TaskLoader.new.create_tasks!
@@ -0,0 +1,52 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ #
5
+ # A team graph reduces a PackageGraph by aggregating over packages owned by teams
6
+ #
7
+ class TeamGraph
8
+ extend T::Sig
9
+ include GraphInterface
10
+
11
+ sig { override.returns(T::Set[NodeInterface]) }
12
+ def nodes
13
+ @team_nodes
14
+ end
15
+
16
+ sig { params(team_nodes: T::Set[TeamNode]).void }
17
+ def initialize(team_nodes:)
18
+ @team_nodes = team_nodes
19
+ end
20
+
21
+ sig { params(package_graph: PackageGraph).returns(TeamGraph) }
22
+ def self.from_package_graph(package_graph)
23
+ team_nodes = T.let(Set.new, T::Set[TeamNode])
24
+ package_graph.package_nodes.group_by(&:team_name).each do |team, package_nodes_for_team|
25
+ violations_by_team = {}
26
+ package_nodes_for_team.map(&:violations_by_package).each do |new_violations_by_package|
27
+ new_violations_by_package.each do |pack_name, count|
28
+ # We first get the pack owner of the violated package
29
+ other_team = package_graph.package_by_name(pack_name).team_name
30
+ violations_by_team[other_team] ||= 0
31
+ # Then we add the violations on that team together
32
+ # TODO: We may want to ignore this if team == other_team to avoid arrows pointing to self, but maybe not!
33
+ violations_by_team[other_team] += count
34
+ end
35
+ end
36
+
37
+ dependencies = Set.new
38
+ package_nodes_for_team.map(&:dependencies).reduce(Set.new, :+).each do |dependency|
39
+ dependencies << package_graph.package_by_name(dependency).team_name
40
+ end
41
+
42
+ team_nodes << TeamNode.new(
43
+ name: team,
44
+ violations_by_team: violations_by_team,
45
+ dependencies: dependencies
46
+ )
47
+ end
48
+
49
+ TeamGraph.new(team_nodes: team_nodes)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,27 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ class TeamNode < T::Struct
5
+ extend T::Sig
6
+ include NodeInterface
7
+
8
+ const :name, String
9
+ const :violations_by_team, T::Hash[String, Integer]
10
+ const :dependencies, T::Set[String]
11
+
12
+ sig { override.returns(T::Hash[String, Integer]) }
13
+ def violations_by_node_name
14
+ violations_by_team
15
+ end
16
+
17
+ sig { override.returns(String) }
18
+ def group_name
19
+ name
20
+ end
21
+
22
+ sig { override.params(node_name: String).returns(T::Boolean) }
23
+ def depends_on?(node_name)
24
+ dependencies.include?(node_name) || (violations_by_node_name[node_name] || 0) > 0
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ # typed: strict
2
+
3
+ module VisualizePackwerk
4
+ require 'visualize_packwerk/railtie' if defined?(Rails)
5
+ require 'parse_packwerk'
6
+ require 'code_ownership'
7
+ require 'package_protections'
8
+ require 'graphviz'
9
+
10
+ require 'visualize_packwerk/node_interface'
11
+ require 'visualize_packwerk/graph_interface'
12
+ require 'visualize_packwerk/team_node'
13
+ require 'visualize_packwerk/package_node'
14
+ require 'visualize_packwerk/team_graph'
15
+ require 'visualize_packwerk/package_graph'
16
+ require 'visualize_packwerk/package_relationships'
17
+ end
data/sorbet/config ADDED
@@ -0,0 +1,2 @@
1
+ --dir
2
+ .
@@ -0,0 +1,76 @@
1
+ # typed: false
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `activesupport` gem.
5
+ # Please instead update this file by running `bin/tapioca gem activesupport`.
6
+
7
+ class FalseClass
8
+ include ::JSON::Ext::Generator::GeneratorMethods::FalseClass
9
+ end
10
+
11
+ class Float < ::Numeric
12
+ include ::JSON::Ext::Generator::GeneratorMethods::Float
13
+ end
14
+
15
+ class IO
16
+ include ::Enumerable
17
+ include ::File::Constants
18
+ end
19
+
20
+ class IO::ConsoleMode
21
+ def echo=(_arg0); end
22
+ def raw(*_arg0); end
23
+ def raw!(*_arg0); end
24
+
25
+ private
26
+
27
+ def initialize_copy(_arg0); end
28
+ end
29
+
30
+ class IO::EAGAINWaitReadable < ::Errno::EAGAIN
31
+ include ::IO::WaitReadable
32
+ end
33
+
34
+ class IO::EAGAINWaitWritable < ::Errno::EAGAIN
35
+ include ::IO::WaitWritable
36
+ end
37
+
38
+ class IO::EINPROGRESSWaitReadable < ::Errno::EINPROGRESS
39
+ include ::IO::WaitReadable
40
+ end
41
+
42
+ class IO::EINPROGRESSWaitWritable < ::Errno::EINPROGRESS
43
+ include ::IO::WaitWritable
44
+ end
45
+
46
+ IO::EWOULDBLOCKWaitReadable = IO::EAGAINWaitReadable
47
+ IO::EWOULDBLOCKWaitWritable = IO::EAGAINWaitWritable
48
+
49
+ class Integer < ::Numeric
50
+ include ::JSON::Ext::Generator::GeneratorMethods::Integer
51
+ end
52
+
53
+ class NameError < ::StandardError
54
+ include ::DidYouMean::Correctable
55
+ end
56
+
57
+ class NilClass
58
+ include ::JSON::Ext::Generator::GeneratorMethods::NilClass
59
+ end
60
+
61
+ class Numeric
62
+ include ::Comparable
63
+ end
64
+
65
+ class Symbol
66
+ include ::Comparable
67
+ end
68
+
69
+ class TrueClass
70
+ include ::JSON::Ext::Generator::GeneratorMethods::TrueClass
71
+ end
72
+
73
+ class URI::Generic
74
+ include ::URI::RFC2396_REGEXP
75
+ include ::URI
76
+ end