outlaw 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.
- data/.gitignore +2 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +35 -0
- data/Rakefile +4 -0
- data/bin/outlaw +6 -0
- data/data/core_classes.txt +103 -0
- data/examples/.outlawed.example +5 -0
- data/lib/outlaw.rb +20 -0
- data/lib/outlaw/enforcement.rb +34 -0
- data/lib/outlaw/law_dsl.rb +69 -0
- data/lib/outlaw/rule.rb +85 -0
- data/lib/outlaw/version.rb +3 -0
- data/outlaw.gemspec +37 -0
- data/test/outlaw_test.rb +181 -0
- data/test/test_helper.rb +3 -0
- metadata +100 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Brian Glusman
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#Outlaw
|
2
|
+
|
3
|
+
##Keep bad code out of your projects. Your idea of bad code, no one elses.
|
4
|
+
|
5
|
+
### Part of MendicantUniversity.org S10 class, personal project.
|
6
|
+
From the included outlawed.rb example file for custom rule definition:
|
7
|
+
|
8
|
+
module Outlaw
|
9
|
+
outlaw "@@", "Class variables are evil"
|
10
|
+
outlaw "protected", "use private or public, protected is silly in ruby"
|
11
|
+
outlaw "module :token end", "nest modules to avoid empty module declarations"
|
12
|
+
outlaw "eval", "never eval, rarely class_eval or instance_eval, but never eval"
|
13
|
+
end
|
14
|
+
|
15
|
+
### Proposed syntax for DSL:
|
16
|
+
|
17
|
+
A defined collection exists for core classes, such that
|
18
|
+
|
19
|
+
outlaw "class :symbol < :core_class",
|
20
|
+
"core classes implemented in c, can cause bad mojo"
|
21
|
+
|
22
|
+
will outlaw subclassing from any core class
|
23
|
+
|
24
|
+
|
25
|
+
Users can extend new defined collections and by creating new constants
|
26
|
+
defined as arrays of variable names to match in example code the same
|
27
|
+
way :core_class is used above
|
28
|
+
|
29
|
+
Disjoin code segments can be provided as a single example (assuming they
|
30
|
+
occur in the same file) by inserting a :disjoint_code_seperator token in
|
31
|
+
the outlawed sample definition. I don't have a good use case for this
|
32
|
+
at present though, and since it will be difficult to handle disjoint
|
33
|
+
code across different files this may not be worthwhile... but similar
|
34
|
+
special case symbol meanings may be useful, and suggestions or examples
|
35
|
+
are welcome.
|
data/Rakefile
ADDED
data/bin/outlaw
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
ARGF
|
2
|
+
ArgumentError
|
3
|
+
Array
|
4
|
+
BasicObject
|
5
|
+
Bignum
|
6
|
+
Binding
|
7
|
+
Class
|
8
|
+
Comparable
|
9
|
+
Complex
|
10
|
+
Continuation
|
11
|
+
Data
|
12
|
+
Dir
|
13
|
+
ENV
|
14
|
+
EOFError
|
15
|
+
Encoding
|
16
|
+
Encoding::CompatibilityError
|
17
|
+
Encoding::Converter
|
18
|
+
Encoding::ConverterNotFoundError
|
19
|
+
Encoding::InvalidByteSequenceError
|
20
|
+
Encoding::UndefinedConversionError
|
21
|
+
EncodingError
|
22
|
+
Enumerable
|
23
|
+
Enumerator
|
24
|
+
Enumerator::Generator
|
25
|
+
Enumerator::Yielder
|
26
|
+
Errno
|
27
|
+
Exception
|
28
|
+
FalseClass
|
29
|
+
Fiber
|
30
|
+
FiberError
|
31
|
+
File
|
32
|
+
File::Constants
|
33
|
+
File::Stat
|
34
|
+
FileTest
|
35
|
+
Fixnum
|
36
|
+
Float
|
37
|
+
FloatDomainError
|
38
|
+
GC
|
39
|
+
GC::Profiler
|
40
|
+
Hash
|
41
|
+
IO
|
42
|
+
IO::WaitReadable
|
43
|
+
IO::WaitWritable
|
44
|
+
IOError
|
45
|
+
IndexError
|
46
|
+
Integer
|
47
|
+
Interrupt
|
48
|
+
Kernel
|
49
|
+
KeyError
|
50
|
+
LoadError
|
51
|
+
LocalJumpError
|
52
|
+
Marshal
|
53
|
+
MatchData
|
54
|
+
Math
|
55
|
+
Math::DomainError
|
56
|
+
Method
|
57
|
+
Module
|
58
|
+
Mutex
|
59
|
+
NameError
|
60
|
+
NilClass
|
61
|
+
NoMemoryError
|
62
|
+
NoMethodError
|
63
|
+
NotImplementedError
|
64
|
+
Numeric
|
65
|
+
Object
|
66
|
+
ObjectSpace
|
67
|
+
Proc
|
68
|
+
Process
|
69
|
+
Process::GID
|
70
|
+
Process::Status
|
71
|
+
Process::Sys
|
72
|
+
Process::UID
|
73
|
+
Random
|
74
|
+
Range
|
75
|
+
RangeError
|
76
|
+
Rational
|
77
|
+
Regexp
|
78
|
+
RegexpError
|
79
|
+
RubyVM
|
80
|
+
RubyVM::Env
|
81
|
+
RubyVM::InstructionSequence
|
82
|
+
RuntimeError
|
83
|
+
ScriptError
|
84
|
+
SecurityError
|
85
|
+
Signal
|
86
|
+
SignalException
|
87
|
+
StandardError
|
88
|
+
StopIteration
|
89
|
+
String
|
90
|
+
Struct
|
91
|
+
Symbol
|
92
|
+
SyntaxError
|
93
|
+
SystemCallError
|
94
|
+
SystemExit
|
95
|
+
SystemStackError
|
96
|
+
Thread
|
97
|
+
ThreadError
|
98
|
+
ThreadGroup
|
99
|
+
Time
|
100
|
+
TrueClass
|
101
|
+
TypeError
|
102
|
+
UnboundMethod
|
103
|
+
ZeroDivisionError
|
@@ -0,0 +1,5 @@
|
|
1
|
+
outlaw "@@", "class variables are evil"
|
2
|
+
outlaw "protected", "use private or public, protected is silly in ruby"
|
3
|
+
outlaw "module :token end", "nest modules to avoid empty module declarations"
|
4
|
+
outlaw "eval", "never eval, rarely class_eval or instance_eval, but never eval"
|
5
|
+
outlaw "class :symbol < :core_class", "core classes implemented in c, can cause bad mojo"
|
data/lib/outlaw.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ripper'
|
2
|
+
require_relative 'outlaw/law_dsl'
|
3
|
+
require_relative 'outlaw/enforcement'
|
4
|
+
require_relative 'outlaw/rule'
|
5
|
+
|
6
|
+
def outlaw(restriction, message)
|
7
|
+
law = Outlaw::LawDSL.parse(restriction, message)
|
8
|
+
Outlaw::Enforcement.add(law)
|
9
|
+
end
|
10
|
+
|
11
|
+
module Outlaw
|
12
|
+
def self.enforce(dir=".")
|
13
|
+
Outlaw::Enforcement.process_directory(dir)
|
14
|
+
end
|
15
|
+
PARAM_TYPES = [:on_const, :on_ident, :on_ivar, :on_cvar]
|
16
|
+
IGNORE_TYPES = [:on_sp, :on_nl, :on_ignored_nl, :on_rparen, :on_lparen]
|
17
|
+
SPECIAL_CASES = [:disjoint_code_seperator] #need to work on naming here
|
18
|
+
CORE_CLASSES_FILE = File.expand_path("../../data/core_classes.txt", __FILE__)
|
19
|
+
CORE_CLASS = File.readlines(CORE_CLASSES_FILE).map &:chomp
|
20
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Outlaw
|
2
|
+
class Enforcement
|
3
|
+
class << self
|
4
|
+
attr_reader :laws
|
5
|
+
def add(law)
|
6
|
+
@laws ||= []
|
7
|
+
@laws << law
|
8
|
+
end
|
9
|
+
|
10
|
+
def process_directory(path)
|
11
|
+
Dir.foreach(path) do |entry|
|
12
|
+
next if entry == '.' or entry == '..'
|
13
|
+
if File.directory?("#{path}/#{entry}")
|
14
|
+
process_directory("#{path}/#{entry}")
|
15
|
+
else
|
16
|
+
handle("#{path}/#{entry}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def handle(file)
|
22
|
+
if file.match(/.rb$/)
|
23
|
+
text = File.open(file) {|f| f.read}
|
24
|
+
laws.each do |law|
|
25
|
+
if law.call(text)
|
26
|
+
puts "Outlaw Violation in file: #{file}\nRestriction:" +
|
27
|
+
"#{law.restriction}\n\n#{law.message}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Outlaw
|
2
|
+
module LawDSL
|
3
|
+
class << self
|
4
|
+
def parse(restriction, message="")
|
5
|
+
tokens = restriction.split
|
6
|
+
parsed_restriction = []
|
7
|
+
tokens.each do |token|
|
8
|
+
case
|
9
|
+
when special_case?(token)
|
10
|
+
next #TODO - handle AST branches/disjoint code/meta-symbols to be defined
|
11
|
+
when multipart?(token) #this handles multi-token literals, Const.new etc
|
12
|
+
parsed_restriction += Ripper.lex(token)
|
13
|
+
.reduce([]){|array, tkn|
|
14
|
+
array << token_type_regex(tkn) }
|
15
|
+
when defined_collection?(token)
|
16
|
+
parsed_restriction << Outlaw.const_get(string_to_sym(token.upcase))
|
17
|
+
when parameter?(token)
|
18
|
+
parsed_restriction << string_to_sym(token)
|
19
|
+
else
|
20
|
+
parsed_restriction += build_regex(token)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
Rule.new(message, restriction, &build_block(parsed_restriction))
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def token_type_regex(token)
|
29
|
+
/#{token[2]}/
|
30
|
+
end
|
31
|
+
|
32
|
+
def parameter?(token)
|
33
|
+
token[0].chr == ':'
|
34
|
+
end
|
35
|
+
|
36
|
+
def special_case?(token)
|
37
|
+
SPECIAL_CASES.include? token
|
38
|
+
end
|
39
|
+
|
40
|
+
def defined_collection?(token)
|
41
|
+
parameter?(token) && Outlaw.const_defined?(string_to_sym(token.upcase))
|
42
|
+
end
|
43
|
+
|
44
|
+
def string_to_sym(str)
|
45
|
+
str[1..-1].to_sym
|
46
|
+
end
|
47
|
+
|
48
|
+
def build_regex(token)
|
49
|
+
#fully expect this hack to come back & haunt me, but passes curr. examples
|
50
|
+
[/\A#{token}/]
|
51
|
+
end
|
52
|
+
|
53
|
+
def multipart?(token)
|
54
|
+
!parameter?(token) && Ripper.lex(token).count > 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_block(pattern)
|
58
|
+
lambda do |file|
|
59
|
+
program = Ripper.tokenize(file)
|
60
|
+
program.each_with_index do |token, index|
|
61
|
+
next unless token.match(pattern.first)
|
62
|
+
return true if Rule.test(program, index, pattern)
|
63
|
+
end
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/outlaw/rule.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Outlaw
|
2
|
+
class Rule
|
3
|
+
NoDetectionBlockProvided = Class.new(StandardError)
|
4
|
+
attr_reader :message, :restriction
|
5
|
+
def initialize(message, restriction, &detection_block)
|
6
|
+
raise NoDetectionBlockProvided unless detection_block
|
7
|
+
@message = message
|
8
|
+
@restriction = restriction
|
9
|
+
@detection_block = detection_block
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(code)
|
13
|
+
@detection_block.call(code)
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def test(program, start_index, pattern)
|
18
|
+
pattern_index = 0
|
19
|
+
params = params_count_hash(pattern)
|
20
|
+
start_index.upto(program.length) do |index|
|
21
|
+
code = program[index]
|
22
|
+
part = pattern[pattern_index]
|
23
|
+
|
24
|
+
next if IGNORE_TYPES.include? token_type(code)
|
25
|
+
return false unless match_token?(code, part, params[part])
|
26
|
+
pattern_index +=1
|
27
|
+
return true if pattern_index >= pattern.length
|
28
|
+
end
|
29
|
+
|
30
|
+
return false
|
31
|
+
# got to end of program without completing pattern
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def match_token?(code, part, parameter)
|
37
|
+
case part
|
38
|
+
when Array
|
39
|
+
match = true if part.include?(code)
|
40
|
+
when Regexp
|
41
|
+
match = true if code.match(part)
|
42
|
+
when Symbol
|
43
|
+
return false unless param_type_equal(token_type(code), part)
|
44
|
+
#check count on first and count down subseq matches
|
45
|
+
if parameter.first.nil? #history of parameter match if any
|
46
|
+
parameter[0] = code
|
47
|
+
parameter[1] -= 1 #first occurrence of parameter
|
48
|
+
match = true
|
49
|
+
else
|
50
|
+
if parameter.first == code
|
51
|
+
parameter[1] -= 1
|
52
|
+
match = true
|
53
|
+
else
|
54
|
+
match = false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
match = false
|
59
|
+
end
|
60
|
+
|
61
|
+
match
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def param_type_equal(lex, param)
|
66
|
+
#for now just check if it's a variable type, not kw, ws or other token
|
67
|
+
PARAM_TYPES.include? lex
|
68
|
+
end
|
69
|
+
|
70
|
+
def token_type(code)
|
71
|
+
Ripper.lex(code).flatten(1)[1] #Ripper's name for token type is returned in array
|
72
|
+
end
|
73
|
+
|
74
|
+
def params_count_hash(pattern)
|
75
|
+
params = Hash.new(0)
|
76
|
+
pattern.each do |element|
|
77
|
+
params[element] += 1 if element.respond_to?(:to_sym)
|
78
|
+
end
|
79
|
+
output = {} #nil is placeholder for matched lex code
|
80
|
+
params.keys.each {|key| output[key] = [nil, params[key]]}
|
81
|
+
output
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/outlaw.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
require "outlaw/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "outlaw"
|
8
|
+
s.version = Outlaw::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Brian Glusman"]
|
11
|
+
s.email = ["brian@neomindlabs.com"]
|
12
|
+
s.homepage = "https://github.com/bglusman/Outlaw"
|
13
|
+
s.summary = "Outlaw helps you enforce your opinions to keep bad code out your projects."
|
14
|
+
s.rubyforge_project = "outlaw"
|
15
|
+
|
16
|
+
s.description = <<-DESC
|
17
|
+
Keep bad code out of your projects. Your idea of bad code, no one elses.
|
18
|
+
|
19
|
+
Outlaw defines an example based DSL for demonstrating anti-patterns and
|
20
|
+
builds a rule for each anti-pattern that it alerts the user to violations
|
21
|
+
when encountered in a project's codebase during scanning.
|
22
|
+
|
23
|
+
Outlaw is a work in progress and contributions, suggestions and forks are welcome.
|
24
|
+
Outlaw was a personal project for Mendicant University, Session 10 in Jan '12
|
25
|
+
DESC
|
26
|
+
|
27
|
+
|
28
|
+
s.files = `git ls-files`.split("\n")
|
29
|
+
s.test_files = `git ls-files -- {test}/*`.split("\n")
|
30
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
31
|
+
s.require_paths = ["lib"]
|
32
|
+
|
33
|
+
s.add_dependency "ripper-plus", "~> 1.3.0"
|
34
|
+
|
35
|
+
s.add_development_dependency "rake", "~> 0.9.0"
|
36
|
+
s.add_development_dependency "minitest"
|
37
|
+
end
|
data/test/outlaw_test.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
module Outlaw
|
4
|
+
describe LawDSL do
|
5
|
+
it "returns a Rule which is called on code and returns true or false" do
|
6
|
+
end
|
7
|
+
|
8
|
+
before do
|
9
|
+
@okay_file = <<CODE
|
10
|
+
class Whatever < Set
|
11
|
+
def okaything(here)
|
12
|
+
@here = here
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module WithContent
|
17
|
+
def sumthin
|
18
|
+
class_eval('1 + 1')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
CODE
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
it "correctly builds rule for class var" do
|
28
|
+
code1 = "@@"
|
29
|
+
rule1 = LawDSL.parse(code1)
|
30
|
+
|
31
|
+
class_var_file = <<CODE
|
32
|
+
def badthing(here)
|
33
|
+
@@here = here
|
34
|
+
end
|
35
|
+
CODE
|
36
|
+
|
37
|
+
class_result = rule1.call(class_var_file)
|
38
|
+
result1a = rule1.call(@okay_file)
|
39
|
+
class_result .must_equal true
|
40
|
+
end
|
41
|
+
|
42
|
+
it "correctly builds rule for protected" do
|
43
|
+
code2 = "protected"
|
44
|
+
rule2 = LawDSL.parse(code2)
|
45
|
+
|
46
|
+
protected_file = <<CODE
|
47
|
+
class Whatever
|
48
|
+
protected
|
49
|
+
def not_really
|
50
|
+
:false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
CODE
|
54
|
+
|
55
|
+
protected_result= rule2.call(protected_file)
|
56
|
+
result2a = rule2.call(@okay_file)
|
57
|
+
|
58
|
+
protected_result.must_equal true
|
59
|
+
result2a .must_equal false
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
it "correctly builds rule for eval" do
|
64
|
+
code3 = "eval"
|
65
|
+
rule3 = LawDSL.parse(code3)
|
66
|
+
|
67
|
+
eval_file = <<CODE
|
68
|
+
def not_really
|
69
|
+
eval('1 + 1')
|
70
|
+
end
|
71
|
+
CODE
|
72
|
+
|
73
|
+
eval_result = rule3.call(eval_file)
|
74
|
+
result3a = rule3.call(@okay_file)
|
75
|
+
|
76
|
+
eval_result.must_equal true
|
77
|
+
result3a.must_equal false
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
it "correctly builds rule for module" do
|
82
|
+
code4 = "module :name end"
|
83
|
+
rule4 = LawDSL.parse(code4)
|
84
|
+
|
85
|
+
module_file = <<CODE
|
86
|
+
module Thing
|
87
|
+
end
|
88
|
+
CODE
|
89
|
+
|
90
|
+
module_result = rule4.call(module_file)
|
91
|
+
result4a = rule4.call(@okay_file)
|
92
|
+
|
93
|
+
module_result.must_equal true
|
94
|
+
result4a.must_equal false
|
95
|
+
end
|
96
|
+
|
97
|
+
it "correctly builds rule for core" do
|
98
|
+
code5 = "class :symbol < :core_class"
|
99
|
+
rule5 = LawDSL.parse(code5)
|
100
|
+
|
101
|
+
core_file = <<CODE
|
102
|
+
class Whatever < String
|
103
|
+
def badthing(here)
|
104
|
+
@here = here
|
105
|
+
end
|
106
|
+
end
|
107
|
+
CODE
|
108
|
+
core_result = rule5.call(core_file)
|
109
|
+
result5a = rule5.call(@okay_file)
|
110
|
+
core_result .must_equal true
|
111
|
+
result5a.must_equal false
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
# it "correctly builds rule for unless else" do
|
116
|
+
# code6 = "unless :symbols
|
117
|
+
# :disjoint_code_seperator
|
118
|
+
# else :more_symbols"
|
119
|
+
# rule6 = LawDSL.parse(code6)
|
120
|
+
|
121
|
+
# core_file = <<CODE
|
122
|
+
# class Whatever < String
|
123
|
+
# def badthing(here)
|
124
|
+
# @here = here
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
# CODE
|
128
|
+
|
129
|
+
it "correctly builds rule for rescue nil" do
|
130
|
+
code7 = "rescue nil"
|
131
|
+
rule7 = LawDSL.parse(code7)
|
132
|
+
|
133
|
+
nil_file = <<CODE
|
134
|
+
begin
|
135
|
+
"hi"
|
136
|
+
rescue nil
|
137
|
+
"bye"
|
138
|
+
end
|
139
|
+
CODE
|
140
|
+
nil_result = rule7.call(nil_file)
|
141
|
+
result7a = rule7.call(@okay_file)
|
142
|
+
nil_result .must_equal true
|
143
|
+
result7a.must_equal false
|
144
|
+
end
|
145
|
+
|
146
|
+
it "correctly builds rule for inherit struct.new" do
|
147
|
+
code8 = "class :symbol < Struct.new"
|
148
|
+
rule8 = LawDSL.parse(code8)
|
149
|
+
|
150
|
+
struct_file = <<CODE
|
151
|
+
class MyClass < Struct.new("Customer", :name, :address)
|
152
|
+
CODE
|
153
|
+
|
154
|
+
struct_result = rule8.call(struct_file)
|
155
|
+
result8a = rule8.call(@okay_file)
|
156
|
+
|
157
|
+
struct_result.must_equal true
|
158
|
+
result8a.must_equal false
|
159
|
+
end
|
160
|
+
|
161
|
+
|
162
|
+
# end
|
163
|
+
|
164
|
+
it "returns a hash with key counts and nil placeholders" do
|
165
|
+
params = Rule.send(:params_count_hash, [/module/, :token1, :token2, :token1, /class/, :token3, /end/])
|
166
|
+
params.keys.size.must_equal 3
|
167
|
+
params[:token1].last.must_equal 2
|
168
|
+
end
|
169
|
+
|
170
|
+
it "returns a hash with key counts and nil placeholders" do
|
171
|
+
params = Rule.send(:params_count_hash, [/module/, :token1, :token2, :token1, /class/, :token3, /end/])
|
172
|
+
params.keys.size.must_equal 3
|
173
|
+
params[:token1].last.must_equal 2
|
174
|
+
end
|
175
|
+
|
176
|
+
it "returns a block from build_block method" do
|
177
|
+
block = LawDSL.send(:build_block,"@@")
|
178
|
+
assert_kind_of Proc, block
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: outlaw
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Glusman
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ripper-plus
|
16
|
+
requirement: &70327141430060 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.3.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70327141430060
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70327141429400 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70327141429400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: minitest
|
38
|
+
requirement: &70327141427520 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70327141427520
|
47
|
+
description: ! " Keep bad code out of your projects. Your idea of bad code, no
|
48
|
+
one elses.\n\n Outlaw defines an example based DSL for demonstrating anti-patterns
|
49
|
+
and\n builds a rule for each anti-pattern that it alerts the user to violations\n
|
50
|
+
\ when encountered in a project's codebase during scanning.\n\n Outlaw
|
51
|
+
is a work in progress and contributions, suggestions and forks are welcome.\n Outlaw
|
52
|
+
was a personal project for Mendicant University, Session 10 in Jan '12\n"
|
53
|
+
email:
|
54
|
+
- brian@neomindlabs.com
|
55
|
+
executables:
|
56
|
+
- outlaw
|
57
|
+
extensions: []
|
58
|
+
extra_rdoc_files: []
|
59
|
+
files:
|
60
|
+
- .gitignore
|
61
|
+
- Gemfile
|
62
|
+
- LICENSE
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- bin/outlaw
|
66
|
+
- data/core_classes.txt
|
67
|
+
- examples/.outlawed.example
|
68
|
+
- lib/outlaw.rb
|
69
|
+
- lib/outlaw/enforcement.rb
|
70
|
+
- lib/outlaw/law_dsl.rb
|
71
|
+
- lib/outlaw/rule.rb
|
72
|
+
- lib/outlaw/version.rb
|
73
|
+
- outlaw.gemspec
|
74
|
+
- test/outlaw_test.rb
|
75
|
+
- test/test_helper.rb
|
76
|
+
homepage: https://github.com/bglusman/Outlaw
|
77
|
+
licenses: []
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
requirements: []
|
95
|
+
rubyforge_project: outlaw
|
96
|
+
rubygems_version: 1.8.11
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Outlaw helps you enforce your opinions to keep bad code out your projects.
|
100
|
+
test_files: []
|