Compare commits

..

2 Commits

Author SHA1 Message Date
Mike Angell
6fd5e4e6ce Use same approach in scope and environment 2019-08-28 23:35:14 +10:00
Mike Angell
56c667d8f9 Simplify context and scopes 2019-08-28 18:00:37 +10:00
9 changed files with 70 additions and 189 deletions

View File

@@ -2,15 +2,9 @@ inherit_from:
- .rubocop_todo.yml - .rubocop_todo.yml
- ./.rubocop_todo.yml - ./.rubocop_todo.yml
require: rubocop-performance
Performance:
Enabled: true
AllCops: AllCops:
Exclude: Exclude:
- 'performance/shopify/*' - 'performance/shopify/*'
- 'vendor/bundle/**/*'
- 'pkg/**' - 'pkg/**'
Metrics/BlockNesting: Metrics/BlockNesting:
@@ -85,6 +79,9 @@ Style/TrailingCommaInArrayLiteral:
Style/TrailingCommaInHashLiteral: Style/TrailingCommaInHashLiteral:
Enabled: false Enabled: false
Layout/IndentHash:
EnforcedStyle: consistent
Style/FormatString: Style/FormatString:
Enabled: false Enabled: false
@@ -109,6 +106,9 @@ Style/RegexpLiteral:
Style/SymbolLiteral: Style/SymbolLiteral:
Enabled: false Enabled: false
Performance/Count:
Enabled: false
Naming/ConstantName: Naming/ConstantName:
Enabled: false Enabled: false

View File

@@ -1,6 +1,6 @@
# This configuration was generated by # This configuration was generated by
# `rubocop --auto-gen-config` # `rubocop --auto-gen-config`
# on 2019-08-27 22:42:50 +1000 using RuboCop version 0.74.0. # on 2019-04-22 19:11:24 -0400 using RuboCop version 0.53.0.
# The point is for the user to remove these configuration records # The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base. # one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new # Note that changes in the inspected code, or installation of new
@@ -8,67 +8,16 @@
# Offense count: 1 # Offense count: 1
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: TreatCommentsAsGroupSeparators, Include. # Configuration parameters: Include, TreatCommentsAsGroupSeparators.
# Include: **/*.gemspec # Include: **/*.gemspec
Gemspec/OrderedDependencies: Gemspec/OrderedDependencies:
Exclude: Exclude:
- 'liquid.gemspec' - 'liquid.gemspec'
# Offense count: 1
# Configuration parameters: Include.
# Include: **/*.gemspec,
Gemspec/RequiredRubyVersion:
Exclude:
- 'liquid.gemspec'
# Offense count: 124
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/AlignArguments:
Enabled: false
# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
# SupportedColonStyles: key, separator, table
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
Layout/AlignHash:
Exclude:
- 'lib/liquid/condition.rb'
- 'lib/liquid/expression.rb'
- 'test/unit/context_unit_test.rb'
# Offense count: 6
# Cop supports --auto-correct.
Layout/ClosingHeredocIndentation:
Exclude:
- 'test/integration/tags/for_tag_test.rb'
# Offense count: 25
# Cop supports --auto-correct.
Layout/EmptyLineAfterGuardClause:
Exclude:
- 'lib/liquid/block.rb'
- 'lib/liquid/block_body.rb'
- 'lib/liquid/context.rb'
- 'lib/liquid/drop.rb'
- 'lib/liquid/lexer.rb'
- 'lib/liquid/parser.rb'
- 'lib/liquid/standardfilters.rb'
- 'lib/liquid/strainer.rb'
- 'lib/liquid/tags/for.rb'
- 'lib/liquid/tags/if.rb'
- 'lib/liquid/tags/include.rb'
- 'lib/liquid/utils.rb'
- 'lib/liquid/variable.rb'
- 'lib/liquid/variable_lookup.rb'
# Offense count: 5 # Offense count: 5
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: squiggly, active_support, powerpack, unindent # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
Layout/IndentHeredoc: Layout/IndentHeredoc:
Exclude: Exclude:
- 'test/integration/tags/for_tag_test.rb' - 'test/integration/tags/for_tag_test.rb'
@@ -83,13 +32,6 @@ Layout/MultilineMethodCallBraceLayout:
- 'test/integration/error_handling_test.rb' - 'test/integration/error_handling_test.rb'
- 'test/unit/strainer_unit_test.rb' - 'test/unit/strainer_unit_test.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment.
Layout/SpaceAroundOperators:
Exclude:
- 'lib/liquid/condition.rb'
# Offense count: 2 # Offense count: 2
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
@@ -104,7 +46,7 @@ Lint/Void:
Exclude: Exclude:
- 'lib/liquid/parse_context.rb' - 'lib/liquid/parse_context.rb'
# Offense count: 52 # Offense count: 53
Metrics/AbcSize: Metrics/AbcSize:
Max: 56 Max: 56
@@ -112,25 +54,27 @@ Metrics/AbcSize:
Metrics/CyclomaticComplexity: Metrics/CyclomaticComplexity:
Max: 13 Max: 13
# Offense count: 114 # Offense count: 112
# Configuration parameters: CountComments, ExcludedMethods. # Configuration parameters: CountComments.
Metrics/MethodLength: Metrics/MethodLength:
Max: 38 Max: 38
# Offense count: 9 # Offense count: 8
Metrics/PerceivedComplexity: Metrics/PerceivedComplexity:
Max: 11 Max: 11
# Offense count: 1 # Offense count: 52
# Cop supports --auto-correct. # Configuration parameters: Blacklist.
# Configuration parameters: PreferredName. # Blacklist: END, (?-mix:EO[A-Z]{1})
Naming/RescuedExceptionsVariableName: Naming/HeredocDelimiterNaming:
Exclude: Exclude:
- 'lib/liquid/context.rb' - 'test/integration/assign_test.rb'
- 'test/integration/capture_test.rb'
- 'test/integration/trim_mode_test.rb'
# Offense count: 20 # Offense count: 23
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
# AllowedNames: io, id, to, by, on, in, at, ip, db # AllowedNames: io, id
Naming/UncommunicativeMethodParamName: Naming/UncommunicativeMethodParamName:
Exclude: Exclude:
- 'example/server/example_servlet.rb' - 'example/server/example_servlet.rb'
@@ -138,22 +82,15 @@ Naming/UncommunicativeMethodParamName:
- 'lib/liquid/context.rb' - 'lib/liquid/context.rb'
- 'lib/liquid/standardfilters.rb' - 'lib/liquid/standardfilters.rb'
- 'lib/liquid/tags/if.rb' - 'lib/liquid/tags/if.rb'
- 'lib/liquid/utils.rb'
- 'lib/liquid/variable.rb' - 'lib/liquid/variable.rb'
- 'test/integration/filter_test.rb' - 'test/integration/filter_test.rb'
- 'test/integration/standard_filter_test.rb' - 'test/integration/standard_filter_test.rb'
- 'test/integration/tags/for_tag_test.rb'
- 'test/integration/template_test.rb' - 'test/integration/template_test.rb'
- 'test/unit/condition_unit_test.rb' - 'test/unit/condition_unit_test.rb'
# Offense count: 3 # Offense count: 12
# Configuration parameters: EnforcedStyle.
# SupportedStyles: inline, group
Style/AccessModifierDeclarations:
Exclude:
- 'lib/liquid/tag.rb'
- 'lib/liquid/tags/include.rb'
- 'test/unit/strainer_unit_test.rb'
# Offense count: 10
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle. # Configuration parameters: EnforcedStyle.
# SupportedStyles: prefer_alias, prefer_alias_method # SupportedStyles: prefer_alias, prefer_alias_method
@@ -180,9 +117,15 @@ Style/ConditionalAssignment:
- 'lib/liquid/errors.rb' - 'lib/liquid/errors.rb'
# Offense count: 1 # Offense count: 1
Style/DateTime:
Exclude:
- 'test/unit/context_unit_test.rb'
# Offense count: 2
# Cop supports --auto-correct. # Cop supports --auto-correct.
Style/EmptyCaseCondition: Style/EmptyCaseCondition:
Exclude: Exclude:
- 'lib/liquid/block_body.rb'
- 'lib/liquid/lexer.rb' - 'lib/liquid/lexer.rb'
# Offense count: 5 # Offense count: 5
@@ -220,13 +163,6 @@ Style/FormatStringToken:
- 'test/integration/filter_test.rb' - 'test/integration/filter_test.rb'
- 'test/integration/hash_ordering_test.rb' - 'test/integration/hash_ordering_test.rb'
# Offense count: 103
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, never
Style/FrozenStringLiteralComment:
Enabled: false
# Offense count: 14 # Offense count: 14
# Configuration parameters: MinBodyLength. # Configuration parameters: MinBodyLength.
Style/GuardClause: Style/GuardClause:
@@ -244,13 +180,6 @@ Style/GuardClause:
- 'lib/liquid/variable.rb' - 'lib/liquid/variable.rb'
- 'test/unit/tokenizer_unit_test.rb' - 'test/unit/tokenizer_unit_test.rb'
# Offense count: 52
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: literals, strict
Style/MutableConstant:
Enabled: false
# Offense count: 1 # Offense count: 1
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, MinBodyLength. # Configuration parameters: EnforcedStyle, MinBodyLength.
@@ -259,9 +188,9 @@ Style/Next:
Exclude: Exclude:
- 'lib/liquid/tags/for.rb' - 'lib/liquid/tags/for.rb'
# Offense count: 13 # Offense count: 4
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. # Configuration parameters: AutoCorrect, EnforcedStyle.
# SupportedStyles: predicate, comparison # SupportedStyles: predicate, comparison
Style/NumericPredicate: Style/NumericPredicate:
Exclude: Exclude:
@@ -270,8 +199,6 @@ Style/NumericPredicate:
- 'lib/liquid/forloop_drop.rb' - 'lib/liquid/forloop_drop.rb'
- 'lib/liquid/standardfilters.rb' - 'lib/liquid/standardfilters.rb'
- 'lib/liquid/tablerowloop_drop.rb' - 'lib/liquid/tablerowloop_drop.rb'
- 'test/integration/standard_filter_test.rb'
- 'test/integration/template_test.rb'
# Offense count: 14 # Offense count: 14
# Cop supports --auto-correct. # Cop supports --auto-correct.
@@ -289,16 +216,6 @@ Style/RedundantSelf:
Exclude: Exclude:
- 'lib/liquid/strainer.rb' - 'lib/liquid/strainer.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, Whitelist.
# Whitelist: present?, blank?, presence, try, try!
Style/SafeNavigation:
Exclude:
- 'lib/liquid/drop.rb'
- 'lib/liquid/strainer.rb'
- 'lib/liquid/tokenizer.rb'
# Offense count: 9 # Offense count: 9
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: AllowAsExpressionSeparator. # Configuration parameters: AllowAsExpressionSeparator.
@@ -336,9 +253,8 @@ Style/WhileUntilModifier:
Exclude: Exclude:
- 'lib/liquid/tags/case.rb' - 'lib/liquid/tags/case.rb'
# Offense count: 650 # Offense count: 648
# Cop supports --auto-correct. # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https # URISchemes: http, https
Metrics/LineLength: Metrics/LineLength:
Max: 294 Max: 294

View File

@@ -1,14 +1,20 @@
language: ruby language: ruby
rvm: rvm:
- 2.1
- 2.2
- 2.3
- 2.4 - 2.4
- 2.5 - 2.5
- &latest_ruby 2.6 - &latest_ruby 2.6
- 2.7
- ruby-head - ruby-head
- jruby-head - jruby-head
- truffleruby # - rbx-2
addons:
apt:
packages:
- libgmp3-dev
matrix: matrix:
include: include:
@@ -18,9 +24,9 @@ matrix:
allow_failures: allow_failures:
- rvm: ruby-head - rvm: ruby-head
- rvm: jruby-head - rvm: jruby-head
- rvm: truffleruby
cache: bundler install:
- bundle install
script: bundle exec rake script: bundle exec rake

View File

@@ -10,16 +10,15 @@ group :benchmark, :test do
gem 'memory_profiler' gem 'memory_profiler'
gem 'terminal-table' gem 'terminal-table'
install_if -> { RUBY_PLATFORM !~ /mingw|mswin|java/ && RUBY_ENGINE != 'truffleruby' } do install_if -> { RUBY_PLATFORM !~ /mingw|mswin|java/ } do
gem 'stackprof' gem 'stackprof'
end end
end end
group :test do group :test do
gem 'rubocop', '~> 0.74.0', require: false gem 'rubocop', '~> 0.53.0'
gem 'rubocop-performance', require: false
platform :mri, :truffleruby do platform :mri do
gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'liquid-tag' gem 'liquid-c', github: 'Shopify/liquid-c', ref: 'liquid-tag'
end end
end end

View File

@@ -19,10 +19,8 @@ task :warn_test do
end end
task :rubocop do task :rubocop do
if RUBY_ENGINE == 'ruby' require 'rubocop/rake_task'
require 'rubocop/rake_task' RuboCop::RakeTask.new
RuboCop::RakeTask.new
end
end end
desc 'runs test suite with both strict and lax parsers' desc 'runs test suite with both strict and lax parsers'
@@ -34,8 +32,8 @@ task :test do
Rake::Task['base_test'].reenable Rake::Task['base_test'].reenable
Rake::Task['base_test'].invoke Rake::Task['base_test'].invoke
if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'truffleruby' if RUBY_ENGINE == 'ruby'
ENV['LIQUID_C'] = '1' ENV['LIQUID-C'] = '1'
ENV['LIQUID_PARSER_MODE'] = 'lax' ENV['LIQUID_PARSER_MODE'] = 'lax'
Rake::Task['base_test'].reenable Rake::Task['base_test'].reenable

View File

@@ -20,21 +20,17 @@ module Liquid
@scopes = [(outer_scope || {})] @scopes = [(outer_scope || {})]
@registers = registers @registers = registers
@errors = [] @errors = []
@interrupts = []
@filters = []
@global_filter = nil
@partial = false @partial = false
@strict_variables = false @strict_variables = false
@resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits) @resource_limits = resource_limits || ResourceLimits.new(Template.default_resource_limits)
squash_instance_assigns_with_environments
@this_stack_used = false
self.exception_renderer = Template.default_exception_renderer self.exception_renderer = Template.default_exception_renderer
if rethrow_errors self.exception_renderer = ->(e) { raise } if rethrow_errors
self.exception_renderer = ->(e) { raise }
end
@interrupts = [] squash_instance_assigns_with_environments
@filters = []
@global_filter = nil
end end
def warnings def warnings
@@ -87,9 +83,9 @@ module Liquid
end end
# Push new local scope on the stack. use <tt>Context#stack</tt> instead # Push new local scope on the stack. use <tt>Context#stack</tt> instead
def push(new_scope = {}) def push
@scopes.unshift(new_scope) @scopes.unshift({})
raise StackLevelError, "Nesting too deep".freeze if @scopes.length > Block::MAX_DEPTH raise StackLevelError, "Nesting too deep".freeze if @scopes.length > (Block::MAX_DEPTH + 1)
end end
# Merge a hash of variables in the current local scope # Merge a hash of variables in the current local scope
@@ -111,31 +107,15 @@ module Liquid
# end # end
# #
# context['var] #=> nil # context['var] #=> nil
def stack(new_scope = nil) def stack
old_stack_used = @this_stack_used push
if new_scope
push(new_scope)
@this_stack_used = true
else
@this_stack_used = false
end
yield yield
ensure ensure
pop if @this_stack_used pop
@this_stack_used = old_stack_used
end
def clear_instance_assigns
@scopes[0] = {}
end end
# Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt> # Only allow String, Numeric, Hash, Array, Proc, Boolean or <tt>Liquid::Drop</tt>
def []=(key, value) def []=(key, value)
unless @this_stack_used
@this_stack_used = true
push({})
end
@scopes[0][key] = value @scopes[0][key] = value
end end
@@ -163,27 +143,12 @@ module Liquid
def find_variable(key, raise_on_not_found: true) def find_variable(key, raise_on_not_found: true)
# This was changed from find() to find_index() because this is a very hot # This was changed from find() to find_index() because this is a very hot
# path and find_index() is optimized in MRI to reduce object allocation # path and find_index() is optimized in MRI to reduce object allocation
index = @scopes.find_index { |s| s.key?(key) }
scope = @scopes[index] if index
variable = nil scope = (index = @scopes.find_index { |s| s.key?(key) }) && @scopes[index]
scope ||= (index = @environments.find_index { |s| s.key?(key) }) && @environments[index]
scope ||= {}
if scope.nil? variable = lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found).to_liquid
@environments.each do |e|
variable = lookup_and_evaluate(e, key, raise_on_not_found: raise_on_not_found)
# When lookup returned a value OR there is no value but the lookup also did not raise
# then it is the value we are looking for.
if !variable.nil? || @strict_variables && raise_on_not_found
scope = e
break
end
end
end
scope ||= @environments.last || @scopes.last
variable ||= lookup_and_evaluate(scope, key, raise_on_not_found: raise_on_not_found)
variable = variable.to_liquid
variable.context = self if variable.respond_to?(:context=) variable.context = self if variable.respond_to?(:context=)
variable variable

View File

@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
s.license = "MIT" s.license = "MIT"
# s.description = "A secure, non-evaling end user template engine with aesthetic markup." # s.description = "A secure, non-evaling end user template engine with aesthetic markup."
s.required_ruby_version = ">= 2.4.0" s.required_ruby_version = ">= 2.1.0"
s.required_rubygems_version = ">= 1.3.7" s.required_rubygems_version = ">= 1.3.7"
s.test_files = Dir.glob("{test}/**/*") s.test_files = Dir.glob("{test}/**/*")

View File

@@ -80,10 +80,7 @@ class VariableTest < Minitest::Test
assigns['test'] = 'Tobi' assigns['test'] = 'Tobi'
assert_equal 'Hello Tobi', template.render!(assigns) assert_equal 'Hello Tobi', template.render!(assigns)
assigns.delete('test') assigns.delete('test')
e = assert_raises(RuntimeError) do assert_equal "Hello ", template.render!(assigns)
template.render!(assigns)
end
assert_equal "Unknown variable 'test'", e.message
end end
def test_multiline_variable def test_multiline_variable

View File

@@ -14,7 +14,7 @@ if env_mode = ENV['LIQUID_PARSER_MODE']
end end
Liquid::Template.error_mode = mode Liquid::Template.error_mode = mode
if ENV['LIQUID_C'] == '1' if ENV['LIQUID-C'] == '1'
puts "-- LIQUID C" puts "-- LIQUID C"
require 'liquid/c' require 'liquid/c'
end end