From eb493f5ac84f2d65fbd1666e1496f0a8deafa27f Mon Sep 17 00:00:00 2001 From: Francesco Rodriguez Date: Thu, 20 Dec 2012 15:42:39 -0500 Subject: update AD::Journey to follow Rails coding conventions --- .../lib/action_dispatch/journey/formatter.rb | 166 +++++++++--------- .../lib/action_dispatch/journey/gtg/builder.rb | 81 ++++----- .../lib/action_dispatch/journey/gtg/simulator.rb | 12 +- .../journey/gtg/transition_table.rb | 49 +++--- .../lib/action_dispatch/journey/nfa/builder.rb | 34 ++-- .../lib/action_dispatch/journey/nfa/simulator.rb | 18 +- .../journey/nfa/transition_table.rb | 61 ++++--- .../lib/action_dispatch/journey/nodes/node.rb | 10 +- .../lib/action_dispatch/journey/parser_extras.rb | 4 +- .../lib/action_dispatch/journey/path/pattern.rb | 61 +++---- actionpack/lib/action_dispatch/journey/route.rb | 8 +- actionpack/lib/action_dispatch/journey/router.rb | 116 ++++++------- .../lib/action_dispatch/journey/router/strexp.rb | 2 +- actionpack/lib/action_dispatch/journey/routes.rb | 16 +- actionpack/lib/action_dispatch/journey/scanner.rb | 51 +++--- actionpack/lib/action_dispatch/journey/visitors.rb | 187 +++++++++++---------- 16 files changed, 439 insertions(+), 437 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb index 106b9c33c3..4a344f71af 100644 --- a/actionpack/lib/action_dispatch/journey/formatter.rb +++ b/actionpack/lib/action_dispatch/journey/formatter.rb @@ -5,17 +5,17 @@ module ActionDispatch class Formatter # :nodoc: attr_reader :routes - def initialize routes + def initialize(routes) @routes = routes @cache = nil end - def generate type, name, options, recall = {}, parameterize = nil - constraints = recall.merge options + def generate(type, name, options, recall = {}, parameterize = nil) + constraints = recall.merge(options) missing_keys = [] match_route(name, constraints) do |route| - parameterized_parts = extract_parameterized_parts route, options, recall, parameterize + parameterized_parts = extract_parameterized_parts(route, options, recall, parameterize) next if !name && route.requirements.empty? && route.parts.empty? missing_keys = missing_keys(route, parameterized_parts) @@ -35,112 +35,110 @@ module ActionDispatch end private - def extract_parameterized_parts route, options, recall, parameterize = nil - constraints = recall.merge options - data = constraints.dup - keys_to_keep = route.parts.reverse.drop_while { |part| - !options.key?(part) || (options[part] || recall[part]).nil? - } | route.required_parts + def extract_parameterized_parts(route, options, recall, parameterize = nil) + constraints = recall.merge(options) + data = constraints.dup - (data.keys - keys_to_keep).each do |bad_key| - data.delete bad_key - end + keys_to_keep = route.parts.reverse.drop_while { |part| + !options.key?(part) || (options[part] || recall[part]).nil? + } | route.required_parts + + (data.keys - keys_to_keep).each do |bad_key| + data.delete(bad_key) + end - parameterized_parts = data.dup + parameterized_parts = data.dup - if parameterize - parameterized_parts.each do |k,v| - parameterized_parts[k] = parameterize.call(k, v) + if parameterize + parameterized_parts.each do |k, v| + parameterized_parts[k] = parameterize.call(k, v) + end end - end - parameterized_parts.keep_if { |_,v| v } - parameterized_parts - end + parameterized_parts.keep_if { |_, v| v } + parameterized_parts + end - def named_routes - routes.named_routes - end + def named_routes + routes.named_routes + end - def match_route name, options - if named_routes.key? name - yield named_routes[name] - else - #routes = possibles(@cache, options.to_a) - routes = non_recursive(cache, options.to_a) + def match_route(name, options) + if named_routes.key?(name) + yield named_routes[name] + else + routes = non_recursive(cache, options.to_a) - hash = routes.group_by { |_, r| - r.score options - } + hash = routes.group_by { |_, r| r.score(options) } - hash.keys.sort.reverse_each do |score| - next if score < 0 + hash.keys.sort.reverse_each do |score| + next if score < 0 - hash[score].sort_by { |i,_| i }.each do |_,route| - yield route + hash[score].sort_by { |i, _| i }.each do |_, route| + yield route + end end end end - end - def non_recursive cache, options - routes = [] - stack = [cache] + def non_recursive(cache, options) + routes = [] + stack = [cache] - while stack.any? - c = stack.shift - routes.concat c[:___routes] if c.key? :___routes + while stack.any? + c = stack.shift + routes.concat(c[:___routes]) if c.key?(:___routes) - options.each do |pair| - stack << c[pair] if c.key? pair + options.each do |pair| + stack << c[pair] if c.key?(pair) + end end - end - routes - end + routes + end - # Returns an array populated with missing keys if any are present. - def missing_keys route, parts - missing_keys = [] - tests = route.path.requirements - route.required_parts.each { |key| - if tests.key? key - missing_keys << key unless /\A#{tests[key]}\Z/ === parts[key] - else - missing_keys << key unless parts[key] - end - } - missing_keys - end + # Returns an array populated with missing keys if any are present. + def missing_keys(route, parts) + missing_keys = [] + tests = route.path.requirements + route.required_parts.each { |key| + if tests.key?(key) + missing_keys << key unless /\A#{tests[key]}\Z/ === parts[key] + else + missing_keys << key unless parts[key] + end + } + missing_keys + end - def possibles cache, options, depth = 0 - cache.fetch(:___routes) { [] } + options.find_all { |pair| - cache.key? pair - }.map { |pair| - possibles(cache[pair], options, depth + 1) - }.flatten(1) - end + def possibles(cache, options, depth = 0) + cache.fetch(:___routes) { [] } + options.find_all { |pair| + cache.key?(pair) + }.map { |pair| + possibles(cache[pair], options, depth + 1) + }.flatten(1) + end - # Returns +true+ if no missing keys are present, otherwise +false+. - def verify_required_parts! route, parts - missing_keys(route, parts).empty? - end + # Returns +true+ if no missing keys are present, otherwise +false+. + def verify_required_parts!(route, parts) + missing_keys(route, parts).empty? + end - def build_cache - root = { :___routes => [] } - routes.each_with_index do |route, i| - leaf = route.required_defaults.inject(root) do |h, tuple| - h[tuple] ||= {} + def build_cache + root = { ___routes: [] } + routes.each_with_index do |route, i| + leaf = route.required_defaults.inject(root) do |h, tuple| + h[tuple] ||= {} + end + (leaf[:___routes] ||= []) << [i, route] end - (leaf[:___routes] ||= []) << [i, route] + root end - root - end - def cache - @cache ||= build_cache - end + def cache + @cache ||= build_cache + end end end end diff --git a/actionpack/lib/action_dispatch/journey/gtg/builder.rb b/actionpack/lib/action_dispatch/journey/gtg/builder.rb index 5f2e7b92ae..7d2791714b 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/builder.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/builder.rb @@ -8,10 +8,10 @@ module ActionDispatch attr_reader :root, :ast, :endpoints - def initialize root - @root = root - @ast = Nodes::Cat.new root, DUMMY - @followpos = nil + def initialize(root) + @root = root + @ast = Nodes::Cat.new root, DUMMY + @followpos = nil end def transition_table @@ -35,21 +35,21 @@ module ActionDispatch to = state_id[Object.new] dtrans[from, to] = sym - dtrans.add_accepting to - ps.each { |state| dtrans.add_memo to, state.memo } + dtrans.add_accepting(to) + ps.each { |state| dtrans.add_memo(to, state.memo) } else dtrans[state_id[s], state_id[u]] = sym - if u.include? DUMMY + if u.include?(DUMMY) to = state_id[u] - accepting = ps.find_all { |l| followpos(l).include? DUMMY } + accepting = ps.find_all { |l| followpos(l).include?(DUMMY) } accepting.each { |accepting_state| - dtrans.add_memo to, accepting_state.memo + dtrans.add_memo(to, accepting_state.memo) } - dtrans.add_accepting state_id[u] + dtrans.add_accepting(state_id[u]) end end @@ -60,7 +60,7 @@ module ActionDispatch dtrans end - def nullable? node + def nullable?(node) case node when Nodes::Group true @@ -73,18 +73,18 @@ module ActionDispatch when Nodes::Terminal !node.left when Nodes::Unary - nullable? node.left + nullable?(node.left) else raise ArgumentError, 'unknown nullable: %s' % node.class.name end end - def firstpos node + def firstpos(node) case node when Nodes::Star firstpos(node.left) when Nodes::Cat - if nullable? node.left + if nullable?(node.left) firstpos(node.left) | firstpos(node.right) else firstpos(node.left) @@ -100,14 +100,14 @@ module ActionDispatch end end - def lastpos node + def lastpos(node) case node when Nodes::Star firstpos(node.left) when Nodes::Or node.children.map { |c| lastpos(c) }.flatten.uniq when Nodes::Cat - if nullable? node.right + if nullable?(node.right) lastpos(node.left) | lastpos(node.right) else lastpos(node.right) @@ -121,40 +121,41 @@ module ActionDispatch end end - def followpos node + def followpos(node) followpos_table[node] end private - def followpos_table - @followpos ||= build_followpos - end - def build_followpos - table = Hash.new { |h,k| h[k] = [] } - @ast.each do |n| - case n - when Nodes::Cat - lastpos(n.left).each do |i| - table[i] += firstpos(n.right) - end - when Nodes::Star - lastpos(n).each do |i| - table[i] += firstpos(n) + def followpos_table + @followpos ||= build_followpos + end + + def build_followpos + table = Hash.new { |h, k| h[k] = [] } + @ast.each do |n| + case n + when Nodes::Cat + lastpos(n.left).each do |i| + table[i] += firstpos(n.right) + end + when Nodes::Star + lastpos(n).each do |i| + table[i] += firstpos(n) + end end end + table end - table - end - def symbol edge - case edge - when Journey::Nodes::Symbol - edge.regexp - else - edge.left + def symbol(edge) + case edge + when Journey::Nodes::Symbol + edge.regexp + else + edge.left + end end - end end end end diff --git a/actionpack/lib/action_dispatch/journey/gtg/simulator.rb b/actionpack/lib/action_dispatch/journey/gtg/simulator.rb index 802d692dd5..58ad803841 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/simulator.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/simulator.rb @@ -6,7 +6,7 @@ module ActionDispatch class MatchData # :nodoc: attr_reader :memos - def initialize memos + def initialize(memos) @memos = memos end end @@ -14,12 +14,12 @@ module ActionDispatch class Simulator # :nodoc: attr_reader :tt - def initialize transition_table + def initialize(transition_table) @tt = transition_table end - def simulate string - input = StringScanner.new string + def simulate(string) + input = StringScanner.new(string) state = [0] while sym = input.scan(%r([/.?]|[^/.?]+)) state = tt.move(state, sym) @@ -31,9 +31,9 @@ module ActionDispatch return if acceptance_states.empty? - memos = acceptance_states.map { |x| tt.memo x }.flatten.compact + memos = acceptance_states.map { |x| tt.memo(x) }.flatten.compact - MatchData.new memos + MatchData.new(memos) end alias :=~ :simulate diff --git a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb index 2c34826bb0..da0cddd93c 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/transition_table.rb @@ -15,7 +15,7 @@ module ActionDispatch @memos = Hash.new { |h,k| h[k] = [] } end - def add_accepting state + def add_accepting(state) @accepting[state] = true end @@ -23,24 +23,24 @@ module ActionDispatch @accepting.keys end - def accepting? state + def accepting?(state) @accepting[state] end - def add_memo idx, memo + def add_memo(idx, memo) @memos[idx] << memo end - def memo idx + def memo(idx) @memos[idx] end - def eclosure t + def eclosure(t) Array(t) end - def move t, a - move_string(t, a).concat move_regexp(t, a) + def move(t, a) + move_string(t, a).concat(move_regexp(t, a)) end def to_json @@ -55,15 +55,15 @@ module ActionDispatch end JSON.dump({ - :regexp_states => simple_regexp, - :string_states => @string_states, - :accepting => @accepting + regexp_states: simple_regexp, + string_states: @string_states, + accepting: @accepting }) end def to_svg - svg = IO.popen("dot -Tsvg", 'w+') { |f| - f.write to_dot + svg = IO.popen('dot -Tsvg', 'w+') { |f| + f.write(to_dot) f.close_write f.readlines } @@ -71,7 +71,7 @@ module ActionDispatch svg.join.sub(/width="[^"]*"/, '').sub(/height="[^"]*"/, '') end - def visualizer paths, title = 'FSM' + def visualizer(paths, title = 'FSM') viz_dir = File.join File.dirname(__FILE__), '..', 'visualizer' fsm_js = File.read File.join(viz_dir, 'fsm.js') fsm_css = File.read File.join(viz_dir, 'fsm.css') @@ -110,7 +110,7 @@ module ActionDispatch template.result(binding) end - def []= from, to, sym + def []=(from, to, sym) case sym when String @string_states[from][sym] = to @@ -136,19 +136,20 @@ module ActionDispatch end private - def move_regexp t, a - return [] if t.empty? - t.map { |s| - @regexp_states[s].map { |re,v| re === a ? v : nil } - }.flatten.compact.uniq - end + def move_regexp(t, a) + return [] if t.empty? - def move_string t, a - return [] if t.empty? + t.map { |s| + @regexp_states[s].map { |re, v| re === a ? v : nil } + }.flatten.compact.uniq + end - t.map { |s| @string_states[s][a] }.compact - end + def move_string(t, a) + return [] if t.empty? + + t.map { |s| @string_states[s][a] }.compact + end end end end diff --git a/actionpack/lib/action_dispatch/journey/nfa/builder.rb b/actionpack/lib/action_dispatch/journey/nfa/builder.rb index 8ba48e097d..ee6494c3e4 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/builder.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/builder.rb @@ -5,23 +5,23 @@ module ActionDispatch module Journey # :nodoc: module NFA # :nodoc: class Visitor < Visitors::Visitor # :nodoc: - def initialize tt + def initialize(tt) @tt = tt @i = -1 end - def visit_CAT node - left = visit node.left - right = visit node.right + def visit_CAT(node) + left = visit(node.left) + right = visit(node.right) - @tt.merge left.last, right.first + @tt.merge(left.last, right.first) [left.first, right.last] end - def visit_GROUP node + def visit_GROUP(node) from = @i += 1 - left = visit node.left + left = visit(node.left) to = @i += 1 @tt.accepting = to @@ -33,14 +33,14 @@ module ActionDispatch [from, to] end - def visit_OR node - from = @i += 1 - children = node.children.map { |c| visit c } - to = @i += 1 + def visit_OR(node) + from = @i += 1 + children = node.children.map { |c| visit(c) } + to = @i += 1 children.each do |child| - @tt[from, child.first] = nil - @tt[child.last, to] = nil + @tt[from, child.first] = nil + @tt[child.last, to] = nil end @tt.accepting = to @@ -48,26 +48,26 @@ module ActionDispatch [from, to] end - def terminal node + def terminal(node) from_i = @i += 1 # new state to_i = @i += 1 # new state @tt[from_i, to_i] = node @tt.accepting = to_i - @tt.add_memo to_i, node.memo + @tt.add_memo(to_i, node.memo) [from_i, to_i] end end class Builder # :nodoc: - def initialize ast + def initialize(ast) @ast = ast end def transition_table tt = TransitionTable.new - Visitor.new(tt).accept @ast + Visitor.new(tt).accept(@ast) tt end end diff --git a/actionpack/lib/action_dispatch/journey/nfa/simulator.rb b/actionpack/lib/action_dispatch/journey/nfa/simulator.rb index c2dfec3e21..5b40da6569 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/simulator.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/simulator.rb @@ -6,7 +6,7 @@ module ActionDispatch class MatchData # :nodoc: attr_reader :memos - def initialize memos + def initialize(memos) @memos = memos end end @@ -14,29 +14,29 @@ module ActionDispatch class Simulator # :nodoc: attr_reader :tt - def initialize transition_table + def initialize(transition_table) @tt = transition_table end - def simulate string - input = StringScanner.new string - state = tt.eclosure 0 + def simulate(string) + input = StringScanner.new(string) + state = tt.eclosure(0) until input.eos? sym = input.scan(%r([/.?]|[^/.?]+)) # FIXME: tt.eclosure is not needed for the GTG - state = tt.eclosure tt.move(state, sym) + state = tt.eclosure(tt.move(state, sym)) end acceptance_states = state.find_all { |s| - tt.accepting? tt.eclosure(s).sort.last + tt.accepting?(tt.eclosure(s).sort.last) } return if acceptance_states.empty? - memos = acceptance_states.map { |x| tt.memo x }.flatten.compact + memos = acceptance_states.map { |x| tt.memo(x) }.flatten.compact - MatchData.new memos + MatchData.new(memos) end alias :=~ :simulate diff --git a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb index c2bb513f01..4446a911b2 100644 --- a/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb +++ b/actionpack/lib/action_dispatch/journey/nfa/transition_table.rb @@ -16,7 +16,7 @@ module ActionDispatch @inverted = nil end - def accepting? state + def accepting?(state) accepting == state end @@ -24,20 +24,20 @@ module ActionDispatch [accepting] end - def add_memo idx, memo + def add_memo(idx, memo) @memos[idx] = memo end - def memo idx + def memo(idx) @memos[idx] end - def []= i, f, s + def []=(i, f, s) @table[f][i] = s end - def merge left, right - @memos[right] = @memos.delete left + def merge(left, right) + @memos[right] = @memos.delete(left) @table[right] = @table.delete(left) end @@ -45,11 +45,10 @@ module ActionDispatch (@table.keys + @table.values.map(&:keys).flatten).uniq end - ### - # Returns a generalized transition graph with reduced states. The states + # Returns a generalized transition graph with reduced states. The states # are reduced like a DFA, but the table must be simulated like an NFA. # - # Edges of the GTG are regular expressions + # Edges of the GTG are regular expressions. def generalized_table gt = GTG::TransitionTable.new marked = {} @@ -80,28 +79,26 @@ module ActionDispatch final_groups.each do |states| id = state_id[states] - gt.add_accepting id + gt.add_accepting(id) save = states.find { |s| @memos.key?(s) && eclosure(s).sort.last == accepting } - gt.add_memo id, memo(save) + gt.add_memo(id, memo(save)) end gt end - ### # Returns set of NFA states to which there is a transition on ast symbol # +a+ from some state +s+ in +t+. - def following_states t, a + def following_states(t, a) Array(t).map { |s| inverted[s][a] }.flatten.uniq end - ### # Returns set of NFA states to which there is a transition on ast symbol # +a+ from some state +s+ in +t+. - def move t, a + def move(t, a) Array(t).map { |s| inverted[s].keys.compact.find_all { |sym| sym === a @@ -113,10 +110,9 @@ module ActionDispatch inverted.values.map(&:keys).flatten.compact.uniq.sort_by { |x| x.to_s } end - ### # Returns a set of NFA states reachable from some NFA state +s+ in set # +t+ on nil-transitions alone. - def eclosure t + def eclosure(t) stack = Array(t) seen = {} children = [] @@ -128,7 +124,7 @@ module ActionDispatch seen[s] = true children << s - stack.concat inverted[s][nil] + stack.concat(inverted[s][nil]) end children.uniq @@ -141,26 +137,27 @@ module ActionDispatch end private - def inverted - return @inverted if @inverted - @inverted = Hash.new { |h,from| - h[from] = Hash.new { |j,s| j[s] = [] } - } + def inverted + return @inverted if @inverted + + @inverted = Hash.new { |h, from| + h[from] = Hash.new { |j, s| j[s] = [] } + } - @table.each { |to, hash| - hash.each { |from, sym| - if sym - sym = Nodes::Symbol === sym ? sym.regexp : sym.left - end + @table.each { |to, hash| + hash.each { |from, sym| + if sym + sym = Nodes::Symbol === sym ? sym.regexp : sym.left + end - @inverted[from][sym] << to + @inverted[from][sym] << to + } } - } - @inverted + @inverted + end end - end end end end diff --git a/actionpack/lib/action_dispatch/journey/nodes/node.rb b/actionpack/lib/action_dispatch/journey/nodes/node.rb index a372a37a90..935442ef66 100644 --- a/actionpack/lib/action_dispatch/journey/nodes/node.rb +++ b/actionpack/lib/action_dispatch/journey/nodes/node.rb @@ -8,7 +8,7 @@ module ActionDispatch attr_accessor :left, :memo - def initialize left + def initialize(left) @left = left @memo = nil end @@ -51,7 +51,7 @@ module ActionDispatch end class Dummy < Literal # :nodoc: - def initialize x = Object.new + def initialize(x = Object.new) super end @@ -71,7 +71,7 @@ module ActionDispatch alias :symbol :regexp DEFAULT_EXP = /[^\.\/\?]+/ - def initialize left + def initialize(left) super @regexp = DEFAULT_EXP end @@ -98,7 +98,7 @@ module ActionDispatch class Binary < Node # :nodoc: attr_accessor :right - def initialize left, right + def initialize(left, right) super(left) @right = right end @@ -113,7 +113,7 @@ module ActionDispatch class Or < Node # :nodoc: attr_reader :children - def initialize children + def initialize(children) @children = children end diff --git a/actionpack/lib/action_dispatch/journey/parser_extras.rb b/actionpack/lib/action_dispatch/journey/parser_extras.rb index 068e46bcbb..14892f4321 100644 --- a/actionpack/lib/action_dispatch/journey/parser_extras.rb +++ b/actionpack/lib/action_dispatch/journey/parser_extras.rb @@ -10,8 +10,8 @@ module ActionDispatch @scanner = Scanner.new end - def parse string - @scanner.scan_setup string + def parse(string) + @scanner.scan_setup(string) do_parse end diff --git a/actionpack/lib/action_dispatch/journey/path/pattern.rb b/actionpack/lib/action_dispatch/journey/path/pattern.rb index e5dc6e7432..4a571ec546 100644 --- a/actionpack/lib/action_dispatch/journey/path/pattern.rb +++ b/actionpack/lib/action_dispatch/journey/path/pattern.rb @@ -4,18 +4,18 @@ module ActionDispatch class Pattern # :nodoc: attr_reader :spec, :requirements, :anchored - def initialize strexp + def initialize(strexp) parser = Journey::Parser.new @anchored = true case strexp when String - @spec = parser.parse strexp + @spec = parser.parse(strexp) @requirements = {} @separators = "/.?" when Router::Strexp - @spec = parser.parse strexp.path + @spec = parser.parse(strexp.path) @requirements = strexp.requirements @separators = strexp.separators.join @anchored = strexp.anchor @@ -61,20 +61,20 @@ module ActionDispatch class RegexpOffsets < Journey::Visitors::Visitor # :nodoc: attr_reader :offsets - def initialize matchers + def initialize(matchers) @matchers = matchers @capture_count = [0] end - def visit node + def visit(node) super @capture_count end - def visit_SYMBOL node + def visit_SYMBOL(node) node = node.to_sym - if @matchers.key? node + if @matchers.key?(node) re = /#{@matchers[node]}|/ @capture_count.push((re.match('').length - 1) + (@capture_count.last || 0)) else @@ -84,51 +84,51 @@ module ActionDispatch end class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc: - def initialize separator, matchers + def initialize(separator, matchers) @separator = separator @matchers = matchers @separator_re = "([^#{separator}]+)" super() end - def accept node + def accept(node) %r{\A#{visit node}\Z} end - def visit_CAT node + def visit_CAT(node) [visit(node.left), visit(node.right)].join end - def visit_SYMBOL node + def visit_SYMBOL(node) node = node.to_sym - return @separator_re unless @matchers.key? node + return @separator_re unless @matchers.key?(node) re = @matchers[node] "(#{re})" end - def visit_GROUP node + def visit_GROUP(node) "(?:#{visit node.left})?" end - def visit_LITERAL node - Regexp.escape node.left + def visit_LITERAL(node) + Regexp.escape(node.left) end alias :visit_DOT :visit_LITERAL - def visit_SLASH node + def visit_SLASH(node) node.left end - def visit_STAR node + def visit_STAR(node) re = @matchers[node.left.to_sym] || '.+' "(#{re})" end end class UnanchoredRegexp < AnchoredRegexp # :nodoc: - def accept node + def accept(node) %r{\A#{visit node}} end end @@ -136,7 +136,7 @@ module ActionDispatch class MatchData # :nodoc: attr_reader :names - def initialize names, offsets, match + def initialize(names, offsets, match) @names = names @offsets = offsets @match = match @@ -146,7 +146,7 @@ module ActionDispatch (length - 1).times.map { |i| self[i + 1] } end - def [] x + def [](x) idx = @offsets[x - 1] + x @match[idx] end @@ -164,9 +164,9 @@ module ActionDispatch end end - def match other + def match(other) return unless match = to_regexp.match(other) - MatchData.new names, offsets, match + MatchData.new(names, offsets, match) end alias :=~ :match @@ -179,16 +179,17 @@ module ActionDispatch end private - def regexp_visitor - @anchored ? AnchoredRegexp : UnanchoredRegexp - end - def offsets - return @offsets if @offsets + def regexp_visitor + @anchored ? AnchoredRegexp : UnanchoredRegexp + end - viz = RegexpOffsets.new @requirements - @offsets = viz.accept spec - end + def offsets + return @offsets if @offsets + + viz = RegexpOffsets.new(@requirements) + @offsets = viz.accept(spec) + end end end end diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb index 2de711f091..d18efd863a 100644 --- a/actionpack/lib/action_dispatch/journey/route.rb +++ b/actionpack/lib/action_dispatch/journey/route.rb @@ -11,7 +11,7 @@ module ActionDispatch ## # +path+ is a path constraint. # +constraints+ is a hash of constraints to be applied to this route. - def initialize name, app, path, constraints, defaults = {} + def initialize(name, app, path, constraints, defaults = {}) constraints = constraints.dup @name = name @app = app @@ -52,7 +52,7 @@ module ActionDispatch path.required_names.map { |x| x.to_sym } + required_defaults.keys end - def score constraints + def score(constraints) required_keys = path.required_names supplied_keys = constraints.map { |k,v| v && k.to_s }.compact @@ -67,7 +67,7 @@ module ActionDispatch end alias :segment_keys :parts - def format path_options + def format(path_options) path_options.delete_if do |key, value| value.to_s == defaults[key].to_s && !required_parts.include?(key) end @@ -86,7 +86,7 @@ module ActionDispatch def required_defaults @required_defaults ||= begin matches = parts - @defaults.dup.delete_if { |k,_| matches.include? k } + @defaults.dup.delete_if { |k,_| matches.include?(k) } end end end diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb index 59351f8e4d..1fc45a2109 100644 --- a/actionpack/lib/action_dispatch/journey/router.rb +++ b/actionpack/lib/action_dispatch/journey/router.rb @@ -22,7 +22,7 @@ module ActionDispatch class NullReq # :nodoc: attr_reader :env - def initialize env + def initialize(env) @env = env end @@ -44,15 +44,15 @@ module ActionDispatch attr_reader :request_class, :formatter attr_accessor :routes - def initialize routes, options + def initialize(routes, options) @options = options @params_key = options[:parameters_key] @request_class = options[:request_class] || NullReq @routes = routes end - def call env - env['PATH_INFO'] = Utils.normalize_path env['PATH_INFO'] + def call(env) + env['PATH_INFO'] = Utils.normalize_path(env['PATH_INFO']) find_routes(env).each do |match, parameters, route| script_name, path_info, set_params = env.values_at('SCRIPT_NAME', @@ -81,7 +81,7 @@ module ActionDispatch return [404, {'X-Cascade' => 'pass'}, ['Not Found']] end - def recognize req + def recognize(req) find_routes(req.env).each do |match, parameters, route| unless route.path.anchored req.env['SCRIPT_NAME'] = match.to_s @@ -96,73 +96,73 @@ module ActionDispatch tt = GTG::Builder.new(ast).transition_table groups = partitioned_routes.first.map(&:ast).group_by { |a| a.to_s } asts = groups.values.map { |v| v.first } - tt.visualizer asts + tt.visualizer(asts) end private - def partitioned_routes - routes.partitioned_routes - end + def partitioned_routes + routes.partitioned_routes + end - def ast - routes.ast - end + def ast + routes.ast + end - def simulator - routes.simulator - end + def simulator + routes.simulator + end - def custom_routes - partitioned_routes.last - end + def custom_routes + partitioned_routes.last + end - def filter_routes path - return [] unless ast - data = simulator.match(path) - data ? data.memos : [] - end + def filter_routes(path) + return [] unless ast + data = simulator.match(path) + data ? data.memos : [] + end - def find_routes env - req = request_class.new env + def find_routes env + req = request_class.new(env) - routes = filter_routes(req.path_info).concat custom_routes.find_all { |r| - r.path.match(req.path_info) - } - routes.concat get_routes_as_head(routes) + routes = filter_routes(req.path_info).concat custom_routes.find_all { |r| + r.path.match(req.path_info) + } + routes.concat get_routes_as_head(routes) - routes.sort_by!(&:precedence).select! { |r| - r.constraints.all? { |k,v| v === req.send(k) } && - r.verb === req.request_method - } - routes.reject! { |r| req.ip && !(r.ip === req.ip) } + routes.sort_by!(&:precedence).select! { |r| + r.constraints.all? { |k, v| v === req.send(k) } && + r.verb === req.request_method + } + routes.reject! { |r| req.ip && !(r.ip === req.ip) } - routes.map! { |r| - match_data = r.path.match(req.path_info) - match_names = match_data.names.map { |n| n.to_sym } - match_values = match_data.captures.map { |v| v && Utils.unescape_uri(v) } - info = Hash[match_names.zip(match_values).find_all { |_,y| y }] + routes.map! { |r| + match_data = r.path.match(req.path_info) + match_names = match_data.names.map { |n| n.to_sym } + match_values = match_data.captures.map { |v| v && Utils.unescape_uri(v) } + info = Hash[match_names.zip(match_values).find_all { |_, y| y }] - [match_data, r.defaults.merge(info), r] - } - end + [match_data, r.defaults.merge(info), r] + } + end - def get_routes_as_head(routes) - precedence = (routes.map(&:precedence).max || 0) + 1 - routes = routes.select { |r| - r.verb === "GET" && !(r.verb === "HEAD") - }.map! { |r| - Route.new(r.name, - r.app, - r.path, - r.conditions.merge(:request_method => "HEAD"), - r.defaults).tap do |route| - route.precedence = r.precedence + precedence - end - } - routes.flatten! - routes - end + def get_routes_as_head(routes) + precedence = (routes.map(&:precedence).max || 0) + 1 + routes = routes.select { |r| + r.verb === "GET" && !(r.verb === "HEAD") + }.map! { |r| + Route.new(r.name, + r.app, + r.path, + r.conditions.merge(request_method: "HEAD"), + r.defaults).tap do |route| + route.precedence = r.precedence + precedence + end + } + routes.flatten! + routes + end end end end diff --git a/actionpack/lib/action_dispatch/journey/router/strexp.rb b/actionpack/lib/action_dispatch/journey/router/strexp.rb index 829ced8039..f97f1a223e 100644 --- a/actionpack/lib/action_dispatch/journey/router/strexp.rb +++ b/actionpack/lib/action_dispatch/journey/router/strexp.rb @@ -8,7 +8,7 @@ module ActionDispatch attr_reader :path, :requirements, :separators, :anchor - def initialize path, requirements, separators, anchor = true + def initialize(path, requirements, separators, anchor = true) @path = path @requirements = requirements @separators = separators diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb index c0966dd794..32829a1f20 100644 --- a/actionpack/lib/action_dispatch/journey/routes.rb +++ b/actionpack/lib/action_dispatch/journey/routes.rb @@ -50,12 +50,11 @@ module ActionDispatch return @simulator if @simulator gtg = GTG::Builder.new(ast).transition_table - @simulator = GTG::Simulator.new gtg + @simulator = GTG::Simulator.new(gtg) end - ### # Add a route to the routing table. - def add_route app, path, conditions, defaults, name = nil + def add_route(app, path, conditions, defaults, name = nil) route = Route.new(name, app, path, conditions, defaults) route.precedence = routes.length @@ -66,11 +65,12 @@ module ActionDispatch end private - def clear_cache! - @ast = nil - @partitioned_routes = nil - @simulator = nil - end + + def clear_cache! + @ast = nil + @partitioned_routes = nil + @simulator = nil + end end end end diff --git a/actionpack/lib/action_dispatch/journey/scanner.rb b/actionpack/lib/action_dispatch/journey/scanner.rb index 668dec0a35..633be11a2d 100644 --- a/actionpack/lib/action_dispatch/journey/scanner.rb +++ b/actionpack/lib/action_dispatch/journey/scanner.rb @@ -7,8 +7,8 @@ module ActionDispatch @ss = nil end - def scan_setup str - @ss = StringScanner.new str + def scan_setup(str) + @ss = StringScanner.new(str) end def eos? @@ -31,30 +31,31 @@ module ActionDispatch end private - def scan - case - # / - when text = @ss.scan(/\//) - [:SLASH, text] - when text = @ss.scan(/\*\w+/) - [:STAR, text] - when text = @ss.scan(/\(/) - [:LPAREN, text] - when text = @ss.scan(/\)/) - [:RPAREN, text] - when text = @ss.scan(/\|/) - [:OR, text] - when text = @ss.scan(/\./) - [:DOT, text] - when text = @ss.scan(/:\w+/) - [:SYMBOL, text] - when text = @ss.scan(/[\w%\-~]+/) - [:LITERAL, text] - # any char - when text = @ss.scan(/./) - [:LITERAL, text] + + def scan + case + # / + when text = @ss.scan(/\//) + [:SLASH, text] + when text = @ss.scan(/\*\w+/) + [:STAR, text] + when text = @ss.scan(/\(/) + [:LPAREN, text] + when text = @ss.scan(/\)/) + [:RPAREN, text] + when text = @ss.scan(/\|/) + [:OR, text] + when text = @ss.scan(/\./) + [:DOT, text] + when text = @ss.scan(/:\w+/) + [:SYMBOL, text] + when text = @ss.scan(/[\w%\-~]+/) + [:LITERAL, text] + # any char + when text = @ss.scan(/./) + [:LITERAL, text] + end end - end end end end diff --git a/actionpack/lib/action_dispatch/journey/visitors.rb b/actionpack/lib/action_dispatch/journey/visitors.rb index 8c055376ca..46bd58c178 100644 --- a/actionpack/lib/action_dispatch/journey/visitors.rb +++ b/actionpack/lib/action_dispatch/journey/visitors.rb @@ -7,69 +7,70 @@ module ActionDispatch h[k] = "visit_#{k}" } - def accept node - visit node + def accept(node) + visit(node) end private - def visit node - send DISPATCH_CACHE[node.type], node - end - def binary node - visit node.left - visit node.right - end - def visit_CAT(n); binary(n); end + def visit node + send(DISPATCH_CACHE[node.type], node) + end - def nary node - node.children.each { |c| visit c } - end - def visit_OR(n); nary(n); end + def binary(node) + visit(node.left) + visit(node.right) + end + def visit_CAT(n); binary(n); end - def unary node - visit node.left - end - def visit_GROUP(n); unary(n); end - def visit_STAR(n); unary(n); end + def nary(node) + node.children.each { |c| visit(c) } + end + def visit_OR(n); nary(n); end - def terminal node; end - %w{ LITERAL SYMBOL SLASH DOT }.each do |t| - class_eval %{ def visit_#{t}(n); terminal(n); end }, __FILE__, __LINE__ - end + def unary(node) + visit(node.left) + end + def visit_GROUP(n); unary(n); end + def visit_STAR(n); unary(n); end + + def terminal(node); end + %w{ LITERAL SYMBOL SLASH DOT }.each do |t| + class_eval %{ def visit_#{t}(n); terminal(n); end }, __FILE__, __LINE__ + end end # Loop through the requirements AST class Each < Visitor # :nodoc: attr_reader :block - def initialize block + def initialize(block) @block = block end - def visit node + def visit(node) super - block.call node + block.call(node) end end class String < Visitor # :nodoc: private - def binary node + def binary(node) [visit(node.left), visit(node.right)].join end - def nary node - node.children.map { |c| visit c }.join '|' + def nary(node) + node.children.map { |c| visit(c) }.join '|' end - def terminal node + def terminal(node) node.left end - def visit_GROUP node - "(#{visit node.left})" + def visit_GROUP(node) + "(#{visit(node.left)})" end end @@ -77,43 +78,44 @@ module ActionDispatch class Formatter < Visitor # :nodoc: attr_reader :options, :consumed - def initialize options + def initialize(options) @options = options @consumed = {} end private - def visit_GROUP node - if consumed == options - nil - else - route = visit node.left - route.include?("\0") ? nil : route + + def visit_GROUP(node) + if consumed == options + nil + else + route = visit(node.left) + route.include?("\0") ? nil : route + end end - end - def terminal node - node.left - end + def terminal(node) + node.left + end - def binary node - [visit(node.left), visit(node.right)].join - end + def binary(node) + [visit(node.left), visit(node.right)].join + end - def nary node - node.children.map { |c| visit c }.join - end + def nary(node) + node.children.map { |c| visit(c) }.join + end - def visit_SYMBOL node - key = node.to_sym + def visit_SYMBOL(node) + key = node.to_sym - if value = options[key] - consumed[key] = value - Router::Utils.escape_path(value) - else - "\0" + if value = options[key] + consumed[key] = value + Router::Utils.escape_path(value) + else + "\0" + end end - end end class Dot < Visitor # :nodoc: @@ -122,7 +124,7 @@ module ActionDispatch @edges = [] end - def accept node + def accept(node) super <<-eodot digraph parse_tree { @@ -136,50 +138,51 @@ module ActionDispatch end private - def binary node - node.children.each do |c| - @edges << "#{node.object_id} -> #{c.object_id};" + + def binary(node) + node.children.each do |c| + @edges << "#{node.object_id} -> #{c.object_id};" + end + super end - super - end - def nary node - node.children.each do |c| - @edges << "#{node.object_id} -> #{c.object_id};" + def nary(node) + node.children.each do |c| + @edges << "#{node.object_id} -> #{c.object_id};" + end + super end - super - end - def unary node - @edges << "#{node.object_id} -> #{node.left.object_id};" - super - end + def unary(node) + @edges << "#{node.object_id} -> #{node.left.object_id};" + super + end - def visit_GROUP node - @nodes << "#{node.object_id} [label=\"()\"];" - super - end + def visit_GROUP(node) + @nodes << "#{node.object_id} [label=\"()\"];" + super + end - def visit_CAT node - @nodes << "#{node.object_id} [label=\"○\"];" - super - end + def visit_CAT(node) + @nodes << "#{node.object_id} [label=\"○\"];" + super + end - def visit_STAR node - @nodes << "#{node.object_id} [label=\"*\"];" - super - end + def visit_STAR(node) + @nodes << "#{node.object_id} [label=\"*\"];" + super + end - def visit_OR node - @nodes << "#{node.object_id} [label=\"|\"];" - super - end + def visit_OR(node) + @nodes << "#{node.object_id} [label=\"|\"];" + super + end - def terminal node - value = node.left + def terminal(node) + value = node.left - @nodes << "#{node.object_id} [label=\"#{value}\"];" - end + @nodes << "#{node.object_id} [label=\"#{value}\"];" + end end end end -- cgit v1.2.3