Refactor to create tags with a parse class method instead of new.

By moving parse out of the initializer, we can call super at the start of
the initializers for subclasses, and avoid the nasty allocate hack.
This commit is contained in:
Dylan Thacker-Smith
2014-03-20 16:10:10 -04:00
parent e190bbba9e
commit d4ecaff8b8
18 changed files with 44 additions and 49 deletions
+1
View File
@@ -3,6 +3,7 @@
## 3.0.0 / not yet released / branch "master" ## 3.0.0 / not yet released / branch "master"
* ... * ...
* Tag#parse is called after initialize, which now takes options instead of tokens as the 3rd argument. See #321 [Dylan Thacker-Smith, dylanahsmith]
* Raise `Liquid::ArgumentError` instead of `::ArgumentError` when filter has wrong number of arguments #309 [Bogdan Gusiev, bogdan] * Raise `Liquid::ArgumentError` instead of `::ArgumentError` when filter has wrong number of arguments #309 [Bogdan Gusiev, bogdan]
* Add a to_s default for liquid drops, see #306 [Adam Doeler, releod] * Add a to_s default for liquid drops, see #306 [Adam Doeler, releod]
* Add strip, lstrip, and rstrip to standard filters [Florian Weingarten, fw42] * Add strip, lstrip, and rstrip to standard filters [Florian Weingarten, fw42]
+1 -1
View File
@@ -31,7 +31,7 @@ module Liquid
# fetch the tag from registered blocks # fetch the tag from registered blocks
if tag = Template.tags[$1] if tag = Template.tags[$1]
new_tag = tag.new_with_options($1, $2, tokens, @options || {}) new_tag = tag.parse($1, $2, tokens, @options)
@blank &&= new_tag.blank? @blank &&= new_tag.blank?
@nodelist << new_tag @nodelist << new_tag
@children << new_tag @children << new_tag
+3 -4
View File
@@ -1,9 +1,8 @@
module Liquid module Liquid
class Document < Block class Document < Block
# we don't need markup to open this block def self.parse(tokens, options={})
def initialize(tokens, options = {}) # we don't need markup to open this block
@options = options super(nil, nil, tokens, options)
parse(tokens)
end end
# There isn't a real delimiter # There isn't a real delimiter
+10 -10
View File
@@ -3,20 +3,20 @@ module Liquid
attr_accessor :options attr_accessor :options
attr_reader :nodelist, :warnings attr_reader :nodelist, :warnings
def self.new_with_options(tag_name, markup, tokens, options) class << self
# Forgive me Matz for I have sinned. I know this code is weird def parse(tag_name, markup, tokens, options)
# but it was necessary to maintain API compatibility. tag = new(tag_name, markup, options)
new_tag = self.allocate tag.parse(tokens)
new_tag.options = options tag
new_tag.send(:initialize, tag_name, markup, tokens) end
new_tag
private :new
end end
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
@tag_name = tag_name @tag_name = tag_name
@markup = markup @markup = markup
@options ||= {} # needs || because might be set before initialize @options = options
parse(tokens)
end end
def parse(tokens) def parse(tokens)
+2 -3
View File
@@ -11,15 +11,14 @@ module Liquid
class Assign < Tag class Assign < Tag
Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/o Syntax = /(#{VariableSignature}+)\s*=\s*(.*)\s*/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
if markup =~ Syntax if markup =~ Syntax
@to = $1 @to = $1
@from = Variable.new($2) @from = Variable.new($2)
else else
raise SyntaxError.new options[:locale].t("errors.syntax.assign") raise SyntaxError.new options[:locale].t("errors.syntax.assign")
end end
super
end end
def render(context) def render(context)
+2 -3
View File
@@ -14,14 +14,13 @@ module Liquid
class Capture < Block class Capture < Block
Syntax = /(\w+)/ Syntax = /(\w+)/
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
if markup =~ Syntax if markup =~ Syntax
@to = $1 @to = $1
else else
raise SyntaxError.new(options[:locale].t("errors.syntax.capture")) raise SyntaxError.new(options[:locale].t("errors.syntax.capture"))
end end
super
end end
def render(context) def render(context)
+2 -3
View File
@@ -3,7 +3,8 @@ module Liquid
Syntax = /(#{QuotedFragment})/o Syntax = /(#{QuotedFragment})/o
WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/o WhenSyntax = /(#{QuotedFragment})(?:(?:\s+or\s+|\s*\,\s*)(#{QuotedFragment}.*))?/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
@blocks = [] @blocks = []
if markup =~ Syntax if markup =~ Syntax
@@ -11,8 +12,6 @@ module Liquid
else else
raise SyntaxError.new(options[:locale].t("errors.syntax.case")) raise SyntaxError.new(options[:locale].t("errors.syntax.case"))
end end
super
end end
def nodelist def nodelist
+2 -2
View File
@@ -15,7 +15,8 @@ module Liquid
SimpleSyntax = /\A#{QuotedFragment}+/o SimpleSyntax = /\A#{QuotedFragment}+/o
NamedSyntax = /\A(#{QuotedFragment})\s*\:\s*(.*)/o NamedSyntax = /\A(#{QuotedFragment})\s*\:\s*(.*)/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
case markup case markup
when NamedSyntax when NamedSyntax
@variables = variables_from_string($2) @variables = variables_from_string($2)
@@ -26,7 +27,6 @@ module Liquid
else else
raise SyntaxError.new(options[:locale].t("errors.syntax.cycle")) raise SyntaxError.new(options[:locale].t("errors.syntax.cycle"))
end end
super
end end
def render(context) def render(context)
+2 -3
View File
@@ -19,10 +19,9 @@ module Liquid
# Hello: -3 # Hello: -3
# #
class Decrement < Tag class Decrement < Tag
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
@variable = markup.strip
super super
@variable = markup.strip
end end
def render(context) def render(context)
+2 -2
View File
@@ -46,10 +46,10 @@ module Liquid
class For < Block class For < Block
Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o Syntax = /\A(#{VariableSegment}+)\s+in\s+(#{QuotedFragment}+)\s*(reversed)?/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
parse_with_selected_parser(markup) parse_with_selected_parser(markup)
@nodelist = @for_block = [] @nodelist = @for_block = []
super
end end
def nodelist def nodelist
+2 -2
View File
@@ -14,10 +14,10 @@ module Liquid
ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o ExpressionsAndOperators = /(?:\b(?:\s?and\s?|\s?or\s?)\b|(?:\s*(?!\b(?:\s?and\s?|\s?or\s?)\b)(?:#{QuotedFragment}|\S+)\s*)+)/o
BOOLEAN_OPERATORS = %w(and or) BOOLEAN_OPERATORS = %w(and or)
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
@blocks = [] @blocks = []
push_block('if', markup) push_block('if', markup)
super
end end
def nodelist def nodelist
+3 -3
View File
@@ -17,7 +17,9 @@ module Liquid
class Include < Tag class Include < Tag
Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o Syntax = /(#{QuotedFragment}+)(\s+(?:with|for)\s+(#{QuotedFragment}+))?/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
if markup =~ Syntax if markup =~ Syntax
@template_name = $1 @template_name = $1
@@ -31,8 +33,6 @@ module Liquid
else else
raise SyntaxError.new(options[:locale].t("errors.syntax.include")) raise SyntaxError.new(options[:locale].t("errors.syntax.include"))
end end
super
end end
def parse(tokens) def parse(tokens)
+2 -2
View File
@@ -15,9 +15,9 @@ module Liquid
# Hello: 2 # Hello: 2
# #
class Increment < Tag class Increment < Tag
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
@variable = markup.strip
super super
@variable = markup.strip
end end
def render(context) def render(context)
+2 -3
View File
@@ -2,7 +2,8 @@ module Liquid
class TableRow < Block class TableRow < Block
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
if markup =~ Syntax if markup =~ Syntax
@variable_name = $1 @variable_name = $1
@collection_name = $2 @collection_name = $2
@@ -13,8 +14,6 @@ module Liquid
else else
raise SyntaxError.new(options[:locale].t("errors.syntax.table_row")) raise SyntaxError.new(options[:locale].t("errors.syntax.table_row"))
end end
super
end end
def render(context) def render(context)
+1 -1
View File
@@ -72,7 +72,7 @@ module Liquid
# Parse source code. # Parse source code.
# Returns self for easy chaining # Returns self for easy chaining
def parse(source, options = {}) def parse(source, options = {})
@root = Document.new(tokenize(source), DEFAULT_OPTIONS.merge(options)) @root = Document.parse(tokenize(source), DEFAULT_OPTIONS.merge(options))
@warnings = nil @warnings = nil
self self
end end
+3 -3
View File
@@ -1,15 +1,15 @@
class CommentForm < Liquid::Block class CommentForm < Liquid::Block
Syntax = /(#{Liquid::VariableSignature}+)/ Syntax = /(#{Liquid::VariableSignature}+)/
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
if markup =~ Syntax if markup =~ Syntax
@variable_name = $1 @variable_name = $1
@attributes = {} @attributes = {}
else else
raise SyntaxError.new("Syntax Error in 'comment_form' - Valid syntax: comment_form [article]") raise SyntaxError.new("Syntax Error in 'comment_form' - Valid syntax: comment_form [article]")
end end
super
end end
def render(context) def render(context)
+3 -3
View File
@@ -1,7 +1,9 @@
class Paginate < Liquid::Block class Paginate < Liquid::Block
Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/ Syntax = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, options)
super
@nodelist = [] @nodelist = []
if markup =~ Syntax if markup =~ Syntax
@@ -19,8 +21,6 @@ class Paginate < Liquid::Block
else else
raise SyntaxError.new("Syntax Error in tag 'paginate' - Valid syntax: paginate [collection] by number") raise SyntaxError.new("Syntax Error in tag 'paginate' - Valid syntax: paginate [collection] by number")
end end
super
end end
def render(context) def render(context)
+1 -1
View File
@@ -4,7 +4,7 @@ class StandardTagTest < Test::Unit::TestCase
include Liquid include Liquid
def test_tag def test_tag
tag = Tag.new('tag', [], []) tag = Tag.parse('tag', [], [], {})
assert_equal 'liquid::tag', tag.name assert_equal 'liquid::tag', tag.name
assert_equal '', tag.render(Context.new) assert_equal '', tag.render(Context.new)
end end