archruby 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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/archruby.gemspec +28 -0
- data/bin/archruby +20 -0
- data/bin/constraints_breaks.yml +29 -0
- data/constraints_breaks.yml +22 -0
- data/lib/archruby.rb +47 -0
- data/lib/archruby/architecture/architecture.rb +83 -0
- data/lib/archruby/architecture/config_definition.rb +66 -0
- data/lib/archruby/architecture/constraint_break.rb +22 -0
- data/lib/archruby/architecture/dependency.rb +11 -0
- data/lib/archruby/architecture/file_content.rb +24 -0
- data/lib/archruby/architecture/module_definition.rb +218 -0
- data/lib/archruby/architecture/parser.rb +58 -0
- data/lib/archruby/presenters/graph.rb +132 -0
- data/lib/archruby/presenters/text.rb +14 -0
- data/lib/archruby/presenters/yaml.rb +28 -0
- data/lib/archruby/ruby/core_library.rb +26 -0
- data/lib/archruby/ruby/parser.rb +409 -0
- data/lib/archruby/ruby/std_library.rb +22 -0
- data/lib/archruby/ruby/var_propagation.rb +46 -0
- data/lib/archruby/version.rb +3 -0
- data/spec/architecture/architecture_spec.rb +48 -0
- data/spec/architecture/config_definition_spec.rb +20 -0
- data/spec/architecture/constraint_break_spec.rb +22 -0
- data/spec/architecture/file_content_spec.rb +12 -0
- data/spec/architecture/module_definition_spec.rb +70 -0
- data/spec/architecture/parser_spec.rb +11 -0
- data/spec/archruby_spec.rb +10 -0
- data/spec/dummy_app/.gitignore +16 -0
- data/spec/dummy_app/Gemfile +45 -0
- data/spec/dummy_app/README.rdoc +28 -0
- data/spec/dummy_app/Rakefile +6 -0
- data/spec/dummy_app/app/assets/images/.keep +0 -0
- data/spec/dummy_app/app/assets/javascripts/application.js +16 -0
- data/spec/dummy_app/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy_app/app/controllers/application_controller.rb +17 -0
- data/spec/dummy_app/app/controllers/concerns/.keep +0 -0
- data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
- data/spec/dummy_app/app/mailers/.keep +0 -0
- data/spec/dummy_app/app/models/.keep +0 -0
- data/spec/dummy_app/app/models/concerns/.keep +0 -0
- data/spec/dummy_app/app/models/module_test.rb +5 -0
- data/spec/dummy_app/app/models/teste.rb +11 -0
- data/spec/dummy_app/app/models/user.rb +9 -0
- data/spec/dummy_app/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy_app/app/views/view_test.rb +5 -0
- data/spec/dummy_app/bin/bundle +3 -0
- data/spec/dummy_app/bin/rails +4 -0
- data/spec/dummy_app/bin/rake +4 -0
- data/spec/dummy_app/config.ru +4 -0
- data/spec/dummy_app/config/application.rb +23 -0
- data/spec/dummy_app/config/boot.rb +4 -0
- data/spec/dummy_app/config/database.yml +25 -0
- data/spec/dummy_app/config/environment.rb +5 -0
- data/spec/dummy_app/config/environments/development.rb +29 -0
- data/spec/dummy_app/config/environments/production.rb +80 -0
- data/spec/dummy_app/config/environments/test.rb +36 -0
- data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy_app/config/initializers/inflections.rb +16 -0
- data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
- data/spec/dummy_app/config/initializers/secret_token.rb +12 -0
- data/spec/dummy_app/config/initializers/session_store.rb +3 -0
- data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy_app/config/locales/en.yml +23 -0
- data/spec/dummy_app/config/routes.rb +56 -0
- data/spec/dummy_app/db/seeds.rb +7 -0
- data/spec/dummy_app/lib/assets/.keep +0 -0
- data/spec/dummy_app/lib/fetch_facebook_info.rb +7 -0
- data/spec/dummy_app/lib/integracao_twitter.rb +5 -0
- data/spec/dummy_app/lib/tasks/.keep +0 -0
- data/spec/dummy_app/log/.keep +0 -0
- data/spec/dummy_app/public/404.html +58 -0
- data/spec/dummy_app/public/422.html +58 -0
- data/spec/dummy_app/public/500.html +57 -0
- data/spec/dummy_app/public/favicon.ico +0 -0
- data/spec/dummy_app/public/robots.txt +5 -0
- data/spec/dummy_app/test/controllers/.keep +0 -0
- data/spec/dummy_app/test/fixtures/.keep +0 -0
- data/spec/dummy_app/test/helpers/.keep +0 -0
- data/spec/dummy_app/test/integration/.keep +0 -0
- data/spec/dummy_app/test/mailers/.keep +0 -0
- data/spec/dummy_app/test/models/.keep +0 -0
- data/spec/dummy_app/test/test_helper.rb +15 -0
- data/spec/dummy_app/vendor/assets/javascripts/.keep +0 -0
- data/spec/dummy_app/vendor/assets/stylesheets/.keep +0 -0
- data/spec/fixtures/new_arch_definition.yml +32 -0
- data/spec/fixtures/ruby_example.rb +74 -0
- data/spec/ruby/parser_spec.rb +45 -0
- data/spec/ruby/var_propagation_spec.rb +22 -0
- data/spec/spec_helper.rb +1 -0
- metadata +295 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module Archruby
|
|
2
|
+
module Architecture
|
|
3
|
+
|
|
4
|
+
class ModuleDefinition
|
|
5
|
+
|
|
6
|
+
ALLOWED_CONSTRAINTS = ['required', 'allowed', 'forbidden']
|
|
7
|
+
|
|
8
|
+
attr_reader :name, :allowed_modules, :required_modules, :forbidden_modules,
|
|
9
|
+
:dependencies, :classes_and_dependencies
|
|
10
|
+
|
|
11
|
+
attr_accessor :classes
|
|
12
|
+
|
|
13
|
+
def initialize config_definition, base_directory
|
|
14
|
+
@config_definition = config_definition
|
|
15
|
+
@name = @config_definition.module_name
|
|
16
|
+
@allowed_modules = @config_definition.allowed_modules
|
|
17
|
+
@required_modules = @config_definition.required_modules
|
|
18
|
+
@forbidden_modules = @config_definition.forbidden_modules
|
|
19
|
+
@base_directory = base_directory
|
|
20
|
+
@files_and_contents = []
|
|
21
|
+
@classes = []
|
|
22
|
+
@dependencies = []
|
|
23
|
+
@classes_and_dependencies = []
|
|
24
|
+
extract_content_of_files
|
|
25
|
+
extract_dependencies
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def extract_content_of_files file_extractor = Archruby::Architecture::FileContent
|
|
29
|
+
return if !@classes.empty?
|
|
30
|
+
file_extractor = file_extractor.new(@base_directory)
|
|
31
|
+
@config_definition.files.each do |file|
|
|
32
|
+
file_content = file_extractor.all_content_from_directory file
|
|
33
|
+
@files_and_contents << file_content
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def extract_dependencies ruby_parser = Archruby::Ruby::Parser
|
|
38
|
+
return if !@classes.empty?
|
|
39
|
+
@files_and_contents.each do |file_and_content|
|
|
40
|
+
file_and_content.each do |file_name, content|
|
|
41
|
+
parser = ruby_parser.new content
|
|
42
|
+
@classes << parser.classes
|
|
43
|
+
@dependencies << parser.dependencies
|
|
44
|
+
@classes_and_dependencies << parser.classes_and_dependencies
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
@classes << @config_definition.gems
|
|
48
|
+
@classes.flatten!
|
|
49
|
+
@dependencies.flatten!
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def is_mine? class_name
|
|
53
|
+
splited_class_name = class_name.split('::')
|
|
54
|
+
first_class_name = splited_class_name.first
|
|
55
|
+
is_mine = false
|
|
56
|
+
if first_class_name.empty?
|
|
57
|
+
#pocurando por um match exato de dependencia
|
|
58
|
+
first_name = splited_class_name[1]
|
|
59
|
+
splited_class_name.shift # retirando o elemento ''
|
|
60
|
+
class_name = splited_class_name.join("::")
|
|
61
|
+
@classes.each do |klass|
|
|
62
|
+
#TODO Arrumar isso com uma expressao regular
|
|
63
|
+
if klass.include?(class_name) && klass.size == class_name.size
|
|
64
|
+
is_mine = true
|
|
65
|
+
break
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
if !is_mine && !@config_definition.gems.empty?
|
|
69
|
+
@classes.each do |klass|
|
|
70
|
+
#TODO Arrumar isso com uma expressao regular
|
|
71
|
+
if klass.include?(first_name) && klass.size == first_name.size
|
|
72
|
+
is_mine = true
|
|
73
|
+
break
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
if !is_mine
|
|
79
|
+
# procurando por acesso a classe que possa ser desse modulo
|
|
80
|
+
class_name = splited_class_name.join("::")
|
|
81
|
+
included_separator = class_name.include?("::")
|
|
82
|
+
@classes.each do |klass|
|
|
83
|
+
#TODO Arrumar isso com uma expressao regular
|
|
84
|
+
if included_separator
|
|
85
|
+
if klass.include?(class_name)
|
|
86
|
+
is_mine = true
|
|
87
|
+
break
|
|
88
|
+
end
|
|
89
|
+
else
|
|
90
|
+
if klass.include?(class_name) && klass.size == class_name.size
|
|
91
|
+
is_mine = true
|
|
92
|
+
break
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
if !is_mine
|
|
98
|
+
# procurando por GEM
|
|
99
|
+
@classes.each do |klass|
|
|
100
|
+
#TODO Arrumar isso com uma expressao regular
|
|
101
|
+
if klass.include?(first_class_name) && klass.size == first_class_name.size
|
|
102
|
+
is_mine = true
|
|
103
|
+
break
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return is_mine
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def is_external?
|
|
112
|
+
!@config_definition.gems.empty?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def is_empty?
|
|
116
|
+
@classes.empty?
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def verify_constraints architecture
|
|
120
|
+
required_breaks = verify_required architecture
|
|
121
|
+
forbidden_breaks = verify_forbidden architecture
|
|
122
|
+
allowed_breaks = verify_allowed architecture
|
|
123
|
+
all_constraints_breaks = [required_breaks, forbidden_breaks, allowed_breaks].flatten
|
|
124
|
+
all_constraints_breaks.delete(nil)
|
|
125
|
+
all_constraints_breaks
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Verifica todas as classes do modulo
|
|
129
|
+
# Cada uma deve, de alguma forma, depender dos modulos que estao listados como required
|
|
130
|
+
def verify_required architecture
|
|
131
|
+
return if @config_definition.required_modules.empty?
|
|
132
|
+
breaks = []
|
|
133
|
+
@classes_and_dependencies.each_with_index do |class_and_depencies, index|
|
|
134
|
+
if class_and_depencies.empty?
|
|
135
|
+
breaks << Archruby::Architecture::ConstraintBreak.new(
|
|
136
|
+
:type => 'absence',
|
|
137
|
+
:module_origin => self.name,
|
|
138
|
+
:module_target => @config_definition.required_modules.first,
|
|
139
|
+
:class_origin => @classes[index],
|
|
140
|
+
:msg => "not implement a required module"
|
|
141
|
+
)
|
|
142
|
+
next
|
|
143
|
+
end
|
|
144
|
+
class_and_depencies.each do |class_name, dependencies|
|
|
145
|
+
dependency_module_names = []
|
|
146
|
+
dependencies.each do |dependency|
|
|
147
|
+
module_name = architecture.module_name(dependency.class_name)
|
|
148
|
+
dependency_module_names << module_name
|
|
149
|
+
end
|
|
150
|
+
@config_definition.required_modules.each do |required_module|
|
|
151
|
+
if !dependency_module_names.include?(required_module)
|
|
152
|
+
breaks << Archruby::Architecture::ConstraintBreak.new(
|
|
153
|
+
:type => 'absence',
|
|
154
|
+
:module_origin => self.name,
|
|
155
|
+
:module_target => required_module,
|
|
156
|
+
:class_origin => class_name,
|
|
157
|
+
:msg => "not implement a required module"
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
breaks
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def verify_forbidden architecture
|
|
167
|
+
return if @config_definition.forbidden_modules.empty?
|
|
168
|
+
breaks = []
|
|
169
|
+
@classes_and_dependencies.each do |class_and_depencies|
|
|
170
|
+
class_and_depencies.each do |class_name, dependencies|
|
|
171
|
+
dependencies.each do |dependency|
|
|
172
|
+
module_name = architecture.module_name(dependency.class_name)
|
|
173
|
+
next if architecture.is_ruby_internals? module_name
|
|
174
|
+
if @config_definition.forbidden_modules.include? module_name
|
|
175
|
+
next if /[A-Z]_+[A-Z]/.match(dependency.class_name)
|
|
176
|
+
breaks << Archruby::Architecture::ConstraintBreak.new(
|
|
177
|
+
:type => 'divergence',
|
|
178
|
+
:class_origin => class_name,
|
|
179
|
+
:line_origin => dependency.line_number,
|
|
180
|
+
:class_target => dependency.class_name,
|
|
181
|
+
:module_origin => self.name,
|
|
182
|
+
:module_target => module_name,
|
|
183
|
+
:msg => "accessing a module which is forbidden")
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
breaks
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def verify_allowed architecture
|
|
192
|
+
return if @config_definition.allowed_modules.empty?
|
|
193
|
+
breaks = []
|
|
194
|
+
@classes_and_dependencies.each do |class_and_depencies|
|
|
195
|
+
class_and_depencies.each do |class_name, dependencies|
|
|
196
|
+
dependencies.each do |dependency|
|
|
197
|
+
module_name = architecture.module_name(dependency.class_name)
|
|
198
|
+
next if architecture.is_ruby_internals? module_name
|
|
199
|
+
if module_name != self.name && !@config_definition.allowed_modules.include?(module_name)
|
|
200
|
+
next if /[A-Z]_+[A-Z]/.match(dependency.class_name)
|
|
201
|
+
breaks << Archruby::Architecture::ConstraintBreak.new(
|
|
202
|
+
:type => 'divergence',
|
|
203
|
+
:class_origin => class_name,
|
|
204
|
+
:line_origin => dependency.line_number,
|
|
205
|
+
:class_target => dependency.class_name,
|
|
206
|
+
:module_origin => self.name,
|
|
207
|
+
:module_target => module_name,
|
|
208
|
+
:msg => "module #{self.name} is not allowed to depend on module #{module_name}")
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
breaks
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Archruby
|
|
4
|
+
module Architecture
|
|
5
|
+
|
|
6
|
+
class Parser
|
|
7
|
+
attr_reader :modules
|
|
8
|
+
|
|
9
|
+
def initialize config_file_path, base_path
|
|
10
|
+
@config_file = config_file_path
|
|
11
|
+
@base_path = base_path
|
|
12
|
+
@modules = []
|
|
13
|
+
parse
|
|
14
|
+
ruby_std_lib_module
|
|
15
|
+
ruby_core_module
|
|
16
|
+
unknow_module
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parse
|
|
20
|
+
parsed_yaml = yaml_parser.load_file @config_file
|
|
21
|
+
parsed_yaml.each do |module_name, definitions|
|
|
22
|
+
begin
|
|
23
|
+
config_definition = Archruby::Architecture::ConfigDefinition.new module_name, definitions
|
|
24
|
+
module_definition = Archruby::Architecture::ModuleDefinition.new config_definition, @base_path
|
|
25
|
+
rescue ArchChecker::MultipleConstraints => e
|
|
26
|
+
STDOUT.puts "The config file is not right: #{e.msg} | err_code: #{e.status_code} | module_definition: #{module_name}"
|
|
27
|
+
exit(e.status_code)
|
|
28
|
+
end
|
|
29
|
+
@modules << module_definition
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def yaml_parser
|
|
34
|
+
YAML
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def ruby_std_lib_module
|
|
38
|
+
config_definition_std_lib = Archruby::Architecture::ConfigDefinition.new Archruby::Ruby::STD_LIB_NAME, {"gems"=>"", "files"=>"", "allowed"=>"", "forbidden" => ""}
|
|
39
|
+
module_definiton_std_lib = Archruby::Architecture::ModuleDefinition.new(config_definition_std_lib, @base_path)
|
|
40
|
+
module_definiton_std_lib.classes = Archruby::Ruby::STD_LIBRARY_CLASSES
|
|
41
|
+
@modules << module_definiton_std_lib
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def ruby_core_module
|
|
45
|
+
config_definition_core = Archruby::Architecture::ConfigDefinition.new Archruby::Ruby::CORE_LIB_NAME, {"gems"=>"", "files"=>"", "allowed"=>"", "forbidden" => ""}
|
|
46
|
+
module_definiton_core = Archruby::Architecture::ModuleDefinition.new(config_definition_core, @base_path)
|
|
47
|
+
module_definiton_core.classes = Archruby::Ruby::CORE_LIBRARY_CLASSES
|
|
48
|
+
@modules << module_definiton_core
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def unknow_module
|
|
52
|
+
config_definition_unknow = Archruby::Architecture::ConfigDefinition.new "unknown", {"gems"=>"unknown", "files"=>"", "allowed"=>"", "forbidden" => ""}
|
|
53
|
+
@modules << Archruby::Architecture::ModuleDefinition.new(config_definition_unknow, @base_path)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'graphviz'
|
|
2
|
+
|
|
3
|
+
module Archruby
|
|
4
|
+
module Presenters
|
|
5
|
+
|
|
6
|
+
class Graph
|
|
7
|
+
|
|
8
|
+
def render architecture
|
|
9
|
+
modules = architecture.modules
|
|
10
|
+
|
|
11
|
+
g = GraphViz.new(:G)
|
|
12
|
+
|
|
13
|
+
g.edge[:color] = "black"
|
|
14
|
+
g.edge[:style] = "filled"
|
|
15
|
+
g.edge[:label] = ""
|
|
16
|
+
|
|
17
|
+
internal = g.subgraph("internal", "label" => "Internal", "color" => "black")
|
|
18
|
+
|
|
19
|
+
external = g.subgraph("external", "label" => "External", "color" => "black", "rank" => "same")
|
|
20
|
+
|
|
21
|
+
nodes = {}
|
|
22
|
+
|
|
23
|
+
internal_nodes = []
|
|
24
|
+
external_nodes = []
|
|
25
|
+
modules.each do |module_definiton|
|
|
26
|
+
next if module_definiton.name == Archruby::Ruby::STD_LIB_NAME || module_definiton.name == Archruby::Ruby::CORE_LIB_NAME
|
|
27
|
+
if module_definiton.is_external?
|
|
28
|
+
nodes[module_definiton.name] = external.add_nodes(module_definiton.name, "shape" => "parallelogram", "color" => "gray60", "style" => "filled")
|
|
29
|
+
external_nodes << nodes[module_definiton.name]
|
|
30
|
+
else
|
|
31
|
+
if module_definiton.is_empty?
|
|
32
|
+
nodes[module_definiton.name] = internal.add_nodes("#{module_definiton.name}\n [empty]", "color" => "gray74", "shape" => "rectangle")
|
|
33
|
+
else
|
|
34
|
+
nodes[module_definiton.name] = internal.add_nodes(module_definiton.name, "color" => "gray92", "style" => "filled", "shape" => "rectangle")
|
|
35
|
+
end
|
|
36
|
+
internal_nodes << nodes[module_definiton.name]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
edges = {}
|
|
41
|
+
edges_objs = []
|
|
42
|
+
|
|
43
|
+
modules.each do |module_definiton|
|
|
44
|
+
module_name = module_definiton.name
|
|
45
|
+
node_origin = nodes[module_name]
|
|
46
|
+
edges[module_name] ||= {}
|
|
47
|
+
edges[module_name][:edges] ||= []
|
|
48
|
+
|
|
49
|
+
module_definiton.dependencies.each do |class_name|
|
|
50
|
+
module_dest = architecture.module_name class_name
|
|
51
|
+
next if module_dest == Archruby::Ruby::STD_LIB_NAME || module_dest == Archruby::Ruby::CORE_LIB_NAME
|
|
52
|
+
how_many_access = architecture.how_many_access_to module_name, module_dest
|
|
53
|
+
if !edges[module_name][:edges].include?(module_dest) && module_dest != module_name
|
|
54
|
+
edges[module_name][:edges] << module_dest
|
|
55
|
+
node_dest = nodes[module_dest]
|
|
56
|
+
edges_objs << internal.add_edges(node_origin, node_dest, :headlabel => how_many_access, :minlen => 2)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
constraints_breaks = architecture.constraints_breaks
|
|
62
|
+
constraints_breaks.each_with_index do |constraint_break, index|
|
|
63
|
+
module_origin = constraint_break.module_origin
|
|
64
|
+
module_target = constraint_break.module_target
|
|
65
|
+
contraint_type = constraint_break.type
|
|
66
|
+
node_origin = nodes[module_origin]
|
|
67
|
+
node_dest = nodes[module_target]
|
|
68
|
+
node_found = false
|
|
69
|
+
edges_objs.each do |edge|
|
|
70
|
+
if edge.node_one == module_origin && edge.node_two == module_target
|
|
71
|
+
if contraint_type == Archruby::Architecture::ConstraintBreak::ABSENSE
|
|
72
|
+
edge.set do |e|
|
|
73
|
+
e.headlabel = "X (##{architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::ABSENSE)})"
|
|
74
|
+
e.color = "red"
|
|
75
|
+
e.style = "bold"
|
|
76
|
+
e.minlen = 2
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
edge.set do |e|
|
|
80
|
+
e.headlabel = "! (##{architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::DIVERGENCE)})"
|
|
81
|
+
e.color = "orange"
|
|
82
|
+
e.style = "bold"
|
|
83
|
+
e.minlen = 2
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
node_found = true
|
|
87
|
+
break
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if !node_found
|
|
92
|
+
if contraint_type == Archruby::Architecture::ConstraintBreak::ABSENSE
|
|
93
|
+
break_count = architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::ABSENSE)
|
|
94
|
+
edges_objs << g.add_edges(node_origin, node_dest, :color => 'red', :headlabel => "X (##{break_count})", 'style' => 'bold', :minlen => 2)
|
|
95
|
+
else
|
|
96
|
+
break_count = architecture.how_many_break(module_origin, module_target, Archruby::Architecture::ConstraintBreak::DIVERGENCE)
|
|
97
|
+
edges_objs << g.add_edges(node_origin, node_dest, :color => 'red', :headlabel => "! (##{break_count})", 'style' => 'bold', :minlen => 2)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
modules.each do |module_definiton|
|
|
103
|
+
next if module_definiton.name == Archruby::Ruby::STD_LIB_NAME || module_definiton.name == Archruby::Ruby::CORE_LIB_NAME
|
|
104
|
+
module_origin = module_definiton.is_empty? ? "#{module_definiton.name}\n [empty]" : module_definiton.name
|
|
105
|
+
node_origin = nodes[module_origin]
|
|
106
|
+
#puts module_definiton.name.inspect
|
|
107
|
+
#puts module_definiton.classes.inspect
|
|
108
|
+
#puts module_definiton.dependencies.inspect
|
|
109
|
+
#puts module_definiton.classes_and_dependencies.inspect
|
|
110
|
+
#puts
|
|
111
|
+
module_definiton.allowed_modules.each do |allowed_module_name|
|
|
112
|
+
module_target = allowed_module_name
|
|
113
|
+
node_dest = nodes[allowed_module_name]
|
|
114
|
+
edge_found = false
|
|
115
|
+
edges_objs.each do |edge|
|
|
116
|
+
if edge.node_one == module_origin && edge.node_two == module_target
|
|
117
|
+
edge_found = true
|
|
118
|
+
break
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
if !edge_found
|
|
122
|
+
internal.add_edges(node_origin, node_dest, :color => 'gray74', :label => "[none]", :minlen => 2)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
g.output( :png => "architecture.png" )
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module ArchChecker
|
|
2
|
+
module Presenters
|
|
3
|
+
class Text
|
|
4
|
+
def render constraint_breaks
|
|
5
|
+
file = File.new('violations.txt', 'w')
|
|
6
|
+
constraint_breaks.each do |constraint_break|
|
|
7
|
+
constraint_break.each do |violations|
|
|
8
|
+
file.puts "#{violations.keys.first} #{violations[violations.keys.first]}"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
3
|
+
module Archruby
|
|
4
|
+
module Presenters
|
|
5
|
+
|
|
6
|
+
class Yaml
|
|
7
|
+
def render architecture
|
|
8
|
+
constraints_breaks = architecture.constraints_breaks
|
|
9
|
+
file = File.new('constraints_breaks.yml', 'w')
|
|
10
|
+
contraints = []
|
|
11
|
+
constraints_breaks.each do |constraint_break|
|
|
12
|
+
constraint = {}
|
|
13
|
+
constraint[constraint_break.type] = {}
|
|
14
|
+
constraint[constraint_break.type]['class_origin'] = constraint_break.class_origin
|
|
15
|
+
constraint[constraint_break.type]['line_origin'] = constraint_break.line_origin
|
|
16
|
+
constraint[constraint_break.type]['class_target'] = constraint_break.class_target
|
|
17
|
+
constraint[constraint_break.type]['module_origin'] = constraint_break.module_origin
|
|
18
|
+
constraint[constraint_break.type]['module_target'] = constraint_break.module_target
|
|
19
|
+
constraint[constraint_break.type]['message'] = constraint_break.msg
|
|
20
|
+
contraints << constraint
|
|
21
|
+
end
|
|
22
|
+
file.write contraints.to_yaml
|
|
23
|
+
file.close
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|