axr 0.6.1 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14c21dbe89798e76d232c029d5cae8843e1a25bc313453abbdb9ff6e3a7feed7
4
- data.tar.gz: 14771453a1f39e857f5cb0edee0670ed332dfd71f90db6ae5e40579703037911
3
+ metadata.gz: 8c8bc4353171b75e8721ae3a01a6094187ec2e88a77cb85a5ee13371807169ef
4
+ data.tar.gz: 80f6aa5204e7603bd6d392b0fcd9e60ce743e1073c1a39308dc69f97dccdbb2d
5
5
  SHA512:
6
- metadata.gz: d04a46e35c7ab0c314ae88dc431ceb373822074b146c92864a6c992df352bb1d53f3e3ee3d13130e23dda6de0463cf3a1455da26caf60b5ef4be29ba7d0824bb
7
- data.tar.gz: 7d586e920c1b053fae07373a41a496a9c4a4a8b1e7de661a3c902ea461d9a8080dafc97b625ab40290e0f3ca5b3912f0d43a38057a41815d37c011b0d6b32fac
6
+ metadata.gz: a8e77aafafe49bebf2f6cde671e5d5e26e39420a32a1f4863e93274f25b5e90b5fc5599d985e047e1feefbfcb778b3a3511ab46acf2e8fad22888a22afc5c8fd
7
+ data.tar.gz: e2ae37f504ae56fe70d67b1310e65e2aa7036f3f46623c293de5ec36fc769351655363a8f1272fae4d090a44fa8b1e9038eaaee51b68c03fbd47745ab2fa33f9
data/.gitignore CHANGED
@@ -7,6 +7,10 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ # development files
11
+ .ruby-gemset
12
+ .ruby-version
13
+
10
14
  # rspec failure tracking
11
15
  .rspec_status
12
16
  *.gem
@@ -1,23 +1,36 @@
1
- require: rubocop-rails
1
+ require: rubocop
2
2
 
3
3
  AllCops:
4
- TargetRubyVersion: 2.6
4
+ TargetRubyVersion: 2.4
5
+ NewCops: disable
5
6
  Exclude:
6
7
  - bin/*
7
8
  - Guardfile
9
+ - vendor/**/*
8
10
 
9
11
  Style/Documentation:
10
12
  Enabled: false
11
13
 
12
- Metrics/LineLength:
14
+ Layout/LineLength:
13
15
  Max: 120
14
16
 
17
+ Metrics/AbcSize:
18
+ Max: 20
19
+
15
20
  Metrics/BlockLength:
16
21
  ExcludedMethods: [
17
- 'describe', 'xdescribe', 'context', 'xcontext', 'it', 'xit', 'let', 'before', 'after', 'aggregate_failures'
22
+ 'describe',
23
+ 'xdescribe',
24
+ 'context',
25
+ 'xcontext',
26
+ 'it',
27
+ 'xit',
28
+ 'let',
29
+ 'before',
30
+ 'after',
31
+ 'aggregate_failures'
18
32
  ]
19
33
 
20
-
21
34
  Metrics/MethodLength:
22
35
  Max: 15
23
36
 
@@ -1,7 +1,13 @@
1
1
  ---
2
- sudo: false
3
2
  language: ruby
4
3
  cache: bundler
5
4
  rvm:
6
- - 2.6.3
7
- before_install: gem install bundler -v 2.0.2
5
+ - 2.5.7
6
+ - 2.6.5
7
+ - 2.7.0
8
+ before_install:
9
+ - gem install bundler
10
+ - bundle install
11
+ script:
12
+ - bundle exec rubocop
13
+ - bundle exec rspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- axr (0.6.0)
4
+ axr (0.8.1)
5
5
  colorize (~> 0.8.1)
6
6
  thor (~> 0.20)
7
7
 
@@ -12,7 +12,7 @@ GEM
12
12
  coderay (1.1.2)
13
13
  colorize (0.8.1)
14
14
  diff-lcs (1.3)
15
- ffi (1.11.1)
15
+ ffi (1.12.2)
16
16
  formatador (0.2.5)
17
17
  guard (2.16.1)
18
18
  formatador (>= 0.2.4)
@@ -29,39 +29,39 @@ GEM
29
29
  guard-compat (~> 1.1)
30
30
  rspec (>= 2.99.0, < 4.0)
31
31
  jaro_winkler (1.5.4)
32
- listen (3.2.0)
32
+ listen (3.2.1)
33
33
  rb-fsevent (~> 0.10, >= 0.10.3)
34
34
  rb-inotify (~> 0.9, >= 0.9.10)
35
- lumberjack (1.0.13)
35
+ lumberjack (1.2.4)
36
36
  method_source (0.9.2)
37
37
  nenv (0.3.0)
38
38
  notiffany (0.1.3)
39
39
  nenv (~> 0.1)
40
40
  shellany (~> 0.0)
41
- parallel (1.18.0)
42
- parser (2.6.5.0)
41
+ parallel (1.19.1)
42
+ parser (2.7.0.5)
43
43
  ast (~> 2.4.0)
44
44
  pry (0.12.2)
45
45
  coderay (~> 1.1.0)
46
46
  method_source (~> 0.9.0)
47
47
  rainbow (3.0.0)
48
- rake (10.5.0)
48
+ rake (12.3.3)
49
49
  rb-fsevent (0.10.3)
50
- rb-inotify (0.10.0)
50
+ rb-inotify (0.10.1)
51
51
  ffi (~> 1.0)
52
52
  rspec (3.9.0)
53
53
  rspec-core (~> 3.9.0)
54
54
  rspec-expectations (~> 3.9.0)
55
55
  rspec-mocks (~> 3.9.0)
56
- rspec-core (3.9.0)
57
- rspec-support (~> 3.9.0)
58
- rspec-expectations (3.9.0)
56
+ rspec-core (3.9.1)
57
+ rspec-support (~> 3.9.1)
58
+ rspec-expectations (3.9.1)
59
59
  diff-lcs (>= 1.2.0, < 2.0)
60
60
  rspec-support (~> 3.9.0)
61
- rspec-mocks (3.9.0)
61
+ rspec-mocks (3.9.1)
62
62
  diff-lcs (>= 1.2.0, < 2.0)
63
63
  rspec-support (~> 3.9.0)
64
- rspec-support (3.9.0)
64
+ rspec-support (3.9.2)
65
65
  rubocop (0.76.0)
66
66
  jaro_winkler (~> 1.5.1)
67
67
  parallel (~> 1.10)
@@ -72,7 +72,7 @@ GEM
72
72
  ruby-progressbar (1.10.1)
73
73
  shellany (0.0.1)
74
74
  thor (0.20.3)
75
- unicode-display_width (1.6.0)
75
+ unicode-display_width (1.6.1)
76
76
 
77
77
  PLATFORMS
78
78
  ruby
@@ -82,7 +82,7 @@ DEPENDENCIES
82
82
  bundler (~> 2.0)
83
83
  guard-rspec (~> 4.7.3)
84
84
  pry (~> 0.12.2)
85
- rake (~> 10.0)
85
+ rake (~> 12.3.3)
86
86
  rspec (~> 3.0)
87
87
  rubocop (~> 0.76.0)
88
88
 
data/README.md CHANGED
@@ -2,33 +2,43 @@
2
2
 
3
3
  **Ruby architecture for simplicity and team adoption**
4
4
 
5
- Architecture is hard. It’s very easy to build a complex system; much harder to build a simple and adaptable one. The code doesn't matter and coding for the sake of writing code is foolish.
5
+ Architecture's hard. It’s very easy to build a complex system. Much harder to build a simple and adaptable solution. The code doesn't matter. Coding for the sake of writing code is foolish.
6
6
 
7
- Few of us get to write software that survives 5-10 years or longer. 90% of our work is garbage that becomes obsolete 1-3 years after release. Most of our work hours are wasted on features that never get shipped.
7
+ Only a few of us get to write software that survives 5-10 years or longer. 90% of our work is garbage that becomes obsolete in 1-3 years after release. Most of our work hours are wasted on features that will never be useful.
8
+
9
+ This is just a reality.
8
10
 
9
- This is just reality.
10
11
 
11
12
  (c) Volodya Sveredyuk
12
13
 
13
- ## Setup
14
+ ## Motivation
15
+ Application engineering it's always about abstractions and how they describe the real world and business which pays our salaries for coding something that might improve it. Maybe. Sometimes.
14
16
 
15
- ```sh
16
- gem install axr
17
- ```
17
+ I hate doing something alone. I am a team player and as a team player, I prefer conventions over configuration. But this is not working with knowledge responsibility segregation inside the software app. In the Ruby world (especially Rails) it's so easy to add a new feature. Just add one line, one dependency, one callback and now you share knowledge about one entity into another entity. More dependencies - more spaghetti and legacy that in future we should REWRITE EVERYTHING!
18
+
19
+ <img src="docs/images/rewrite.png" alt="drawing" width="500"/>
20
+
21
+ Architecture's about knowledge responsibility and not the code.
22
+
23
+ The worst thing that even we write the architecture document wherein a convenient way to agree on architecture and layers and entities, etc - We are not protected from violation of these conventions.
24
+
25
+ And this the place where AxR comes on the stage.
26
+
27
+ Please, welcome the **DSL** that helps:
28
+ 1. Describes your application layers (modules)
29
+ 2. Defines knowledge responsibilities between them
30
+ 3. Checks if you did not violate anything
31
+
32
+ ## Setup
18
33
 
19
- or in your Gemfile
34
+ In your Gemfile
20
35
  ```ruby
21
36
  gem 'axr'
22
37
  ```
23
38
 
24
- in console
25
- ```sh
26
- bundle install
27
- ```
28
-
29
39
  ## DSL
30
40
 
31
- In your ruby app: (for rails app put it into `config/initializers`)
41
+ In your ruby app: (for rails app put it into `config/initializers/axr.rb` file)
32
42
  ```ruby
33
43
  require 'axr'
34
44
 
@@ -104,6 +114,11 @@ Run for a specific file
104
114
  axr lib/adapters/youtube.rb
105
115
  ```
106
116
 
117
+ Finish scanning with status code 1 in case of any warnings (you can use in CI environment to fail pipeline step)
118
+ ```sh
119
+ axr check --exit-on-warnings
120
+ ```
121
+
107
122
  ## More examples
108
123
 
109
124
  **ERP system**
@@ -111,20 +126,26 @@ axr lib/adapters/youtube.rb
111
126
  <img src="docs/images/erp_example.png" alt="drawing" width="500"/>
112
127
 
113
128
  ```ruby
114
- require 'axr'
115
-
116
- AxR.app.define(isolated: true) do
117
- layer 'Api', familiar_with: ['ERP']
118
- layer 'UI', familiar_with: ['ERP']
119
- layer 'ERP', familiar_with: %w[Inventory Sales Supply]
120
- layer 'Sales', familiar_with: 'Inventory'
121
- layer 'Supply', familiar_with: 'Inventory'
122
- layer 'Repo'
123
- layer 'Change'
124
- layer 'Query'
129
+ if Rails.env.development? || Rails.env.test?
130
+ require 'axr'
131
+
132
+ AxR.app.define(isolated: true) do
133
+ layer 'UI', familiar_with: %w[Docs Inventory Production]
134
+ layer 'API', familiar_with: %w[Docs Inventory Production]
135
+ layer 'Docs', familiar_with: %w[Inventory Accounts Repo]
136
+ layer 'Accounts', familiar_with: %w[Repo]
137
+ layer 'Inventory', familiar_with: %w[Repo]
138
+ layer 'Production', familiar_with: %w[Repo]
139
+ layer 'Repo'
140
+ end
125
141
  end
142
+
126
143
  ```
127
144
 
128
145
  ### TODO
146
+ - Ignore vendor or any other directories dir as configuration
129
147
  - Add sublayers
130
- - Add `axr check --exit-on-warning` cli flag
148
+ - Add rubocop cop
149
+ - Add more app examples
150
+ - Migrate to AST analyzer
151
+
@@ -14,6 +14,8 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'https://github.com/sveredyuk/axr'
15
15
  spec.license = 'MIT'
16
16
 
17
+ spec.required_ruby_version = '>= 2.4.0'
18
+
17
19
  spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
18
20
 
19
21
  spec.metadata['homepage_uri'] = spec.homepage
@@ -30,12 +32,12 @@ Gem::Specification.new do |spec|
30
32
  spec.require_paths = 'lib'
31
33
 
32
34
  spec.add_dependency 'colorize', '~> 0.8.1'
33
- spec.add_dependency 'thor', '~> 0.20'
35
+ spec.add_dependency 'thor', '~> 0.20'
34
36
 
35
- spec.add_development_dependency 'bundler', '~> 2.0'
37
+ spec.add_development_dependency 'bundler', '~> 2.0'
36
38
  spec.add_development_dependency 'guard-rspec', '~> 4.7.3'
37
- spec.add_development_dependency 'pry', '~> 0.12.2'
38
- spec.add_development_dependency 'rake', '~> 10.0'
39
- spec.add_development_dependency 'rspec', '~> 3.0'
40
- spec.add_development_dependency 'rubocop', '~> 0.76.0'
39
+ spec.add_development_dependency 'pry', '~> 0.12.2'
40
+ spec.add_development_dependency 'rake', '~> 12.3.3'
41
+ spec.add_development_dependency 'rspec', '~> 3.0'
42
+ spec.add_development_dependency 'rubocop', '~> 0.76.0'
41
43
  end
Binary file
Binary file
@@ -32,17 +32,21 @@ module AxR
32
32
  end
33
33
 
34
34
  # rubocop:disable Metrics/AbcSize
35
+ # rubocop:disable Metrics/CyclomaticComplexity
36
+ # rubocop:disable Metrics/PerceivedComplexity
35
37
  def legal?(context, dependncy)
36
38
  ctx = layers.find { |l| l.name.to_s == context.to_s }
37
39
  dep = layers.find { |l| l.name.to_s == dependncy.to_s }
38
40
 
39
41
  return false unless ctx && dep
40
42
  return false if ctx.isolated? && ctx.familiar_with.empty?
41
- return true if ctx.familiar_with.map(&:to_s).include?(dependncy.to_s)
43
+ return true if ctx.familiar_with.map(&:to_s).include?(dependncy.to_s)
42
44
 
43
45
  ctx.level < dep.level
44
46
  end
45
47
  # rubocop:enable Metrics/AbcSize
48
+ # rubocop:enable Metrics/CyclomaticComplexity
49
+ # rubocop:enable Metrics/PerceivedComplexity
46
50
 
47
51
  private
48
52
 
@@ -4,15 +4,18 @@ require 'thor'
4
4
 
5
5
  module AxR
6
6
  class CLI < Thor
7
- desc 'check PATH', 'Start AxR runner'
7
+ desc 'check PATH', 'Start AxR runner'
8
+ desc '--load APP_INIT_PATH', 'Specify file to load your ruby application'
9
+ desc '--exit-on-warnings', 'Finish with status code 1 on any warnings'
8
10
 
9
- option :format # TODO: Add formats
10
- option :load # TODO: Add formats
11
+ option :format # TODO: Add more output formats
12
+ option :load
13
+ option :'exit-on-warnings'
11
14
 
12
15
  def check(pattern = nil)
13
16
  $LOAD_PATH << Dir.pwd
14
17
  require options['load'] if options['load']
15
- AxR::Runner.new(pattern).invoke
18
+ AxR::Runner.new(pattern, exit_on_warnings: !options['exit-on-warnings'].nil?).invoke
16
19
  end
17
20
  end
18
21
  end
@@ -7,33 +7,33 @@ module AxR
7
7
  class Runner
8
8
  DOT_RB = '.rb'
9
9
 
10
- attr_reader :target, :formatter
10
+ attr_reader :target, :formatter, :exit_on_warnings
11
11
 
12
- def initialize(target = nil, formatter: AxR::Formatters::Default.new)
13
- @target = target
14
- @formatter = formatter
12
+ def initialize(target = nil, formatter: AxR::Formatters::Default.new, exit_on_warnings: false)
13
+ @target = target
14
+ @formatter = formatter
15
+ @exit_on_warnings = exit_on_warnings
15
16
  end
16
17
 
18
+ alias exit_on_warnings? exit_on_warnings
19
+
17
20
  def invoke
18
21
  files_with_warnings = files_to_scan.each_with_object({}) do |file_path, issues|
19
- scan_result = AxR::Scanner.new(file_path: file_path).scan
22
+ scan_result = AxR::Scanner.new(source: File.open(file_path)).scan
20
23
  issues[file_path] = scan_result.warnings if scan_result.warnings.any?
24
+
21
25
  formatter.single_file(scan_result, file_path)
22
26
  end
23
27
 
24
28
  formatter.summary(files_to_scan, files_with_warnings)
25
29
 
26
- # exit 1 if files_with_warnings.any?
30
+ exit 1 if exit_on_warnings? && files_with_warnings.any?
27
31
 
28
32
  files_with_warnings
29
33
  end
30
34
 
31
35
  def files_to_scan
32
- @files_to_scan ||= if scan_single_file?
33
- [target]
34
- else
35
- Dir.glob("#{target_dir}**/*.rb")
36
- end
36
+ @files_to_scan ||= scan_single_file? ? [target] : Dir.glob("#{target_dir}**/*#{DOT_RB}")
37
37
  end
38
38
 
39
39
  private
@@ -5,34 +5,40 @@ require_relative 'scanner/warning'
5
5
 
6
6
  module AxR
7
7
  class Scanner
8
- attr_reader :file_path, :context, :dependecies, :warnings
8
+ attr_reader :source, :context, :dependecies, :warnings
9
9
 
10
- def initialize(file_path:)
11
- @file_path = file_path
10
+ def initialize(source: [])
11
+ @source = source
12
12
  @dependecies = []
13
13
  @warnings = []
14
14
  @context = nil
15
15
  end
16
16
 
17
17
  # rubocop:disable Metrics/AbcSize
18
+ # rubocop:disable Metrics/CyclomaticComplexity
19
+ # rubocop:disable Metrics/PerceivedComplexity
18
20
  def scan
19
- File.open(file_path).each.with_index do |line, index|
21
+ source.each.with_index do |line, index|
20
22
  loc_num = index + 1
21
23
 
22
24
  line_detection = AxR.app.layer_names.detect { |layer| line.include?(layer) }
23
25
  line_detection = check_space_before(line, line_detection)
24
- context_detection = AxR.app.layer_names.detect { |layer| line.include?("module #{layer}") }
26
+ line_detection = nil if context && module_definition?(line, line_detection)
27
+ line_detection = nil if commented?(line, line_detection)
28
+ context_detection = AxR.app.layer_names.detect { |layer| module_definition?(line, layer) }
25
29
 
26
- next unless line_detection || context_detection
30
+ next unless context_detection || line_detection
27
31
 
28
32
  detect_context(context_detection, line, loc_num) if context_detection && !context
29
33
  detect_dependency(line_detection, line, loc_num)
30
- detect_warning(line_detection, line, loc_num) if context
34
+ detect_warning(line_detection, line, loc_num) if context && line_detection
31
35
  end
32
36
 
33
37
  self
34
38
  end
35
39
  # rubocop:enable Metrics/AbcSize
40
+ # rubocop:enable Metrics/CyclomaticComplexity
41
+ # rubocop:enable Metrics/PerceivedComplexity
36
42
 
37
43
  private
38
44
 
@@ -66,5 +72,19 @@ module AxR
66
72
 
67
73
  line_detection if line[line.index(line_detection) - 1] == SPACE
68
74
  end
75
+
76
+ MODULE = 'module'
77
+
78
+ def module_definition?(line, layer)
79
+ line.include?("#{MODULE} #{layer}")
80
+ end
81
+
82
+ COMMENT = '#'
83
+
84
+ def commented?(line, layer)
85
+ return false if line.empty? || layer.nil?
86
+
87
+ line.split(layer).first&.include?(COMMENT)
88
+ end
69
89
  end
70
90
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AxR
4
- VERSION = '0.6.1'
4
+ VERSION = '0.8.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: axr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodya Sveredyuk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-02 00:00:00.000000000 Z
11
+ date: 2020-08-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: 12.3.3
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '10.0'
96
+ version: 12.3.3
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +147,7 @@ files:
147
147
  - bin/setup
148
148
  - docs/images/abcde_example.png
149
149
  - docs/images/erp_example.png
150
+ - docs/images/rewrite.png
150
151
  - exe/axr
151
152
  - lib/axr.rb
152
153
  - lib/axr/app.rb
@@ -175,14 +176,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
176
  requirements:
176
177
  - - ">="
177
178
  - !ruby/object:Gem::Version
178
- version: '0'
179
+ version: 2.4.0
179
180
  required_rubygems_version: !ruby/object:Gem::Requirement
180
181
  requirements:
181
182
  - - ">="
182
183
  - !ruby/object:Gem::Version
183
184
  version: '0'
184
185
  requirements: []
185
- rubygems_version: 3.0.6
186
+ rubygems_version: 3.1.2
186
187
  signing_key:
187
188
  specification_version: 4
188
189
  summary: Code checker for AxR compliance.