puppet 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +8 -35
  3. data/ext/debian/puppet.default +0 -5
  4. data/ext/debian/puppet.init +1 -15
  5. data/lib/hiera/puppet_function.rb +15 -4
  6. data/lib/puppet/application/agent.rb +5 -0
  7. data/lib/puppet/application/apply.rb +23 -2
  8. data/lib/puppet/application/device.rb +8 -3
  9. data/lib/puppet/application/master.rb +16 -5
  10. data/lib/puppet/configurer.rb +7 -5
  11. data/lib/puppet/defaults.rb +18 -0
  12. data/lib/puppet/environments.rb +1 -1
  13. data/lib/puppet/error.rb +27 -1
  14. data/lib/puppet/file_serving/metadata.rb +13 -8
  15. data/lib/puppet/file_serving/terminus_helper.rb +7 -8
  16. data/lib/puppet/file_system.rb +13 -0
  17. data/lib/puppet/file_system/file_impl.rb +4 -0
  18. data/lib/puppet/file_system/memory_impl.rb +4 -0
  19. data/lib/puppet/file_system/windows.rb +8 -0
  20. data/lib/puppet/functions.rb +33 -3
  21. data/lib/puppet/functions/defined.rb +130 -0
  22. data/lib/puppet/functions/regsubst.rb +1 -1
  23. data/lib/puppet/functions/split.rb +1 -1
  24. data/lib/puppet/indirector/catalog/compiler.rb +1 -1
  25. data/lib/puppet/indirector/facts/facter.rb +11 -0
  26. data/lib/puppet/loaders.rb +1 -0
  27. data/lib/puppet/node.rb +17 -1
  28. data/lib/puppet/node/environment.rb +4 -0
  29. data/lib/puppet/parser/ast/pops_bridge.rb +4 -0
  30. data/lib/puppet/parser/compiler.rb +9 -0
  31. data/lib/puppet/parser/functions/defined.rb +25 -1
  32. data/lib/puppet/parser/functions/file.rb +3 -1
  33. data/lib/puppet/parser/scope.rb +11 -2
  34. data/lib/puppet/parser/templatewrapper.rb +2 -1
  35. data/lib/puppet/pops.rb +4 -0
  36. data/lib/puppet/pops/evaluator/access_operator.rb +25 -5
  37. data/lib/puppet/pops/evaluator/closure.rb +28 -2
  38. data/lib/puppet/pops/evaluator/collector_transformer.rb +1 -11
  39. data/lib/puppet/pops/evaluator/collectors/catalog_collector.rb +4 -0
  40. data/lib/puppet/pops/evaluator/collectors/exported_collector.rb +4 -0
  41. data/lib/puppet/pops/evaluator/compare_operator.rb +43 -0
  42. data/lib/puppet/pops/evaluator/epp_evaluator.rb +7 -2
  43. data/lib/puppet/pops/evaluator/evaluator_impl.rb +48 -14
  44. data/lib/puppet/pops/evaluator/runtime3_support.rb +10 -5
  45. data/lib/puppet/pops/functions/dispatch.rb +6 -1
  46. data/lib/puppet/pops/functions/dispatcher.rb +7 -1
  47. data/lib/puppet/pops/issue_reporter.rb +42 -16
  48. data/lib/puppet/pops/issues.rb +116 -2
  49. data/lib/puppet/pops/loader/loader.rb +11 -0
  50. data/lib/puppet/pops/loader/loader_paths.rb +67 -6
  51. data/lib/puppet/pops/loader/module_loaders.rb +19 -8
  52. data/lib/puppet/pops/loader/puppet_function_instantiator.rb +78 -0
  53. data/lib/puppet/pops/loaders.rb +6 -4
  54. data/lib/puppet/pops/migration/migration_checker.rb +54 -0
  55. data/lib/puppet/pops/model/factory.rb +5 -1
  56. data/lib/puppet/pops/model/model_label_provider.rb +2 -0
  57. data/lib/puppet/pops/model/model_meta.rb +5 -1
  58. data/lib/puppet/pops/parser/egrammar.ra +9 -10
  59. data/lib/puppet/pops/parser/eparser.rb +1061 -1047
  60. data/lib/puppet/pops/parser/epp_support.rb +18 -9
  61. data/lib/puppet/pops/parser/evaluating_parser.rb +7 -1
  62. data/lib/puppet/pops/parser/heredoc_support.rb +12 -11
  63. data/lib/puppet/pops/parser/interpolation_support.rb +7 -1
  64. data/lib/puppet/pops/parser/lexer2.rb +29 -12
  65. data/lib/puppet/pops/parser/lexer_support.rb +52 -23
  66. data/lib/puppet/pops/parser/parser_support.rb +11 -14
  67. data/lib/puppet/pops/parser/slurp_support.rb +22 -6
  68. data/lib/puppet/pops/types/type_calculator.rb +156 -55
  69. data/lib/puppet/pops/types/type_factory.rb +66 -13
  70. data/lib/puppet/pops/types/type_parser.rb +22 -13
  71. data/lib/puppet/pops/types/types.rb +23 -4
  72. data/lib/puppet/pops/types/types_meta.rb +13 -2
  73. data/lib/puppet/pops/validation.rb +25 -2
  74. data/lib/puppet/pops/validation/checker4_0.rb +63 -31
  75. data/lib/puppet/provider/group/windows_adsi.rb +8 -4
  76. data/lib/puppet/provider/mount/parsed.rb +145 -2
  77. data/lib/puppet/provider/package/apt.rb +1 -1
  78. data/lib/puppet/provider/package/pip.rb +11 -2
  79. data/lib/puppet/provider/package/pkgng.rb +134 -0
  80. data/lib/puppet/provider/package/portage.rb +1 -1
  81. data/lib/puppet/provider/package/ports.rb +0 -3
  82. data/lib/puppet/provider/package/windows/exe_package.rb +0 -1
  83. data/lib/puppet/provider/package/windows/msi_package.rb +0 -1
  84. data/lib/puppet/provider/package/zypper.rb +50 -15
  85. data/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +32 -7
  86. data/lib/puppet/provider/service/debian.rb +1 -1
  87. data/lib/puppet/provider/service/init.rb +7 -0
  88. data/lib/puppet/provider/user/openbsd.rb +1 -0
  89. data/lib/puppet/provider/user/windows_adsi.rb +45 -2
  90. data/lib/puppet/reference/indirection.rb +1 -1
  91. data/lib/puppet/resource.rb +1 -1
  92. data/lib/puppet/resource/catalog.rb +0 -4
  93. data/lib/puppet/settings.rb +19 -0
  94. data/lib/puppet/type/file.rb +1 -0
  95. data/lib/puppet/type/file/ensure.rb +1 -1
  96. data/lib/puppet/type/mount.rb +9 -1
  97. data/lib/puppet/type/scheduled_task.rb +13 -0
  98. data/lib/puppet/type/tidy.rb +3 -1
  99. data/lib/puppet/type/user.rb +32 -0
  100. data/lib/puppet/type/yumrepo.rb +5 -5
  101. data/lib/puppet/util/log.rb +50 -8
  102. data/lib/puppet/util/log/destinations.rb +23 -2
  103. data/lib/puppet/util/logging.rb +37 -1
  104. data/lib/puppet/util/run_mode.rb +1 -14
  105. data/lib/puppet/util/windows/adsi.rb +130 -58
  106. data/lib/puppet/version.rb +1 -1
  107. data/man/man5/puppet.conf.5 +48 -6
  108. data/man/man8/extlookup2hiera.8 +1 -1
  109. data/man/man8/puppet-agent.8 +4 -1
  110. data/man/man8/puppet-apply.8 +4 -1
  111. data/man/man8/puppet-ca.8 +1 -1
  112. data/man/man8/puppet-catalog.8 +1 -1
  113. data/man/man8/puppet-cert.8 +1 -1
  114. data/man/man8/puppet-certificate.8 +1 -1
  115. data/man/man8/puppet-certificate_request.8 +1 -1
  116. data/man/man8/puppet-certificate_revocation_list.8 +1 -1
  117. data/man/man8/puppet-config.8 +1 -1
  118. data/man/man8/puppet-describe.8 +1 -1
  119. data/man/man8/puppet-device.8 +6 -3
  120. data/man/man8/puppet-doc.8 +1 -1
  121. data/man/man8/puppet-epp.8 +1 -1
  122. data/man/man8/puppet-facts.8 +1 -1
  123. data/man/man8/puppet-file.8 +1 -1
  124. data/man/man8/puppet-filebucket.8 +1 -1
  125. data/man/man8/puppet-help.8 +1 -1
  126. data/man/man8/puppet-inspect.8 +1 -1
  127. data/man/man8/puppet-key.8 +1 -1
  128. data/man/man8/puppet-man.8 +1 -1
  129. data/man/man8/puppet-master.8 +4 -1
  130. data/man/man8/puppet-module.8 +1 -1
  131. data/man/man8/puppet-node.8 +1 -1
  132. data/man/man8/puppet-parser.8 +1 -1
  133. data/man/man8/puppet-plugin.8 +1 -1
  134. data/man/man8/puppet-report.8 +1 -1
  135. data/man/man8/puppet-resource.8 +1 -1
  136. data/man/man8/puppet-resource_type.8 +1 -1
  137. data/man/man8/puppet-status.8 +1 -1
  138. data/man/man8/puppet.8 +1 -1
  139. data/spec/fixtures/unit/data_providers/environments/production/lib/puppet/functions/environment/data.rb +3 -1
  140. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/functions/data.pp +6 -0
  141. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/lib/puppet/bindings/xyz/default.rb +9 -0
  142. data/spec/fixtures/unit/data_providers/environments/production/modules/xyz/manifests/init.pp +9 -0
  143. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcalled.pp +3 -0
  144. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller.pp +3 -0
  145. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/functions/puppetcaller4.pp +3 -0
  146. data/spec/fixtures/unit/pops/loaders/loaders/mix_4x_and_3x_functions/user/lib/puppet/functions/user/callingpuppet.rb +5 -0
  147. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/functions/hello.pp +3 -0
  148. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/manifests/init.pp +3 -0
  149. data/spec/fixtures/unit/pops/loaders/loaders/module_no_lib/modules/modulea/metadata.json +10 -0
  150. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/hello.pp +3 -0
  151. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/functions/subspace/hello.pp +3 -0
  152. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +1 -10
  153. data/spec/fixtures/unit/provider/mount/parsed/aix.filesystems +93 -85
  154. data/spec/fixtures/unit/provider/mount/parsed/aix.mount +11 -7
  155. data/spec/fixtures/unit/provider/package/pkgng/pkg.info +8 -0
  156. data/spec/fixtures/unit/provider/package/pkgng/pkg.query +1 -0
  157. data/spec/fixtures/unit/provider/package/pkgng/pkg.query_absent +1 -0
  158. data/spec/fixtures/unit/provider/package/pkgng/pkg.version +3 -0
  159. data/spec/fixtures/unit/provider/package/zypper/zypper-list-updates-empty.out +3 -0
  160. data/spec/integration/application/apply_spec.rb +49 -0
  161. data/spec/integration/faces/plugin_spec.rb +0 -4
  162. data/spec/integration/indirector/facts/facter_spec.rb +59 -0
  163. data/spec/integration/parser/compiler_spec.rb +850 -0
  164. data/spec/integration/parser/resource_expressions_spec.rb +3 -0
  165. data/spec/integration/parser/scope_spec.rb +26 -5
  166. data/spec/integration/transaction_spec.rb +1 -1
  167. data/spec/integration/type/file_spec.rb +318 -41
  168. data/spec/integration/util/windows/security_spec.rb +14 -5
  169. data/spec/lib/matchers/resource.rb +22 -1
  170. data/spec/lib/puppet_spec/matchers.rb +6 -4
  171. data/spec/unit/application/master_spec.rb +33 -7
  172. data/spec/unit/data_providers/function_data_provider_spec.rb +10 -1
  173. data/spec/unit/file_serving/metadata_spec.rb +1 -1
  174. data/spec/unit/file_serving/terminus_helper_spec.rb +2 -3
  175. data/spec/unit/file_system_spec.rb +38 -0
  176. data/spec/unit/functions/defined_spec.rb +289 -0
  177. data/spec/unit/functions/hiera_spec.rb +8 -6
  178. data/spec/unit/functions/regsubst_spec.rb +4 -0
  179. data/spec/unit/functions/split_spec.rb +8 -0
  180. data/spec/unit/functions4_spec.rb +97 -2
  181. data/spec/unit/indirector/facts/facter_spec.rb +7 -0
  182. data/spec/unit/node_spec.rb +6 -0
  183. data/spec/unit/parser/functions/file_spec.rb +7 -1
  184. data/spec/unit/parser/functions/template_spec.rb +1 -1
  185. data/spec/unit/parser/scope_spec.rb +2 -2
  186. data/spec/unit/parser/templatewrapper_spec.rb +1 -1
  187. data/spec/unit/pops/evaluator/access_ops_spec.rb +19 -0
  188. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +84 -18
  189. data/spec/unit/pops/evaluator/variables_spec.rb +1 -1
  190. data/spec/unit/pops/issues_spec.rb +16 -16
  191. data/spec/unit/pops/loaders/loaders_spec.rb +106 -48
  192. data/spec/unit/pops/migration_spec.rb +53 -0
  193. data/spec/unit/pops/parser/lexer2_spec.rb +142 -1
  194. data/spec/unit/pops/parser/parse_heredoc_spec.rb +26 -0
  195. data/spec/unit/pops/types/type_calculator_spec.rb +205 -12
  196. data/spec/unit/pops/validation_spec.rb +66 -0
  197. data/spec/unit/pops/validator/validator_spec.rb +1 -1
  198. data/spec/unit/provider/group/windows_adsi_spec.rb +57 -9
  199. data/spec/unit/provider/mount/parsed_spec.rb +31 -5
  200. data/spec/unit/provider/package/apt_spec.rb +5 -0
  201. data/spec/unit/provider/package/pip_spec.rb +9 -0
  202. data/spec/unit/provider/package/pkgng_spec.rb +172 -0
  203. data/spec/unit/provider/package/windows/exe_package_spec.rb +0 -1
  204. data/spec/unit/provider/package/windows/msi_package_spec.rb +0 -1
  205. data/spec/unit/provider/package/zypper_spec.rb +50 -19
  206. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +312 -70
  207. data/spec/unit/provider/service/base_spec.rb +38 -27
  208. data/spec/unit/provider/service/debian_spec.rb +8 -0
  209. data/spec/unit/provider/service/freebsd_spec.rb +1 -0
  210. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  211. data/spec/unit/provider/service/init_spec.rb +18 -0
  212. data/spec/unit/provider/service/openbsd_spec.rb +1 -0
  213. data/spec/unit/provider/service/redhat_spec.rb +1 -0
  214. data/spec/unit/provider/user/windows_adsi_spec.rb +134 -5
  215. data/spec/unit/settings_spec.rb +11 -0
  216. data/spec/unit/util/log_spec.rb +113 -0
  217. data/spec/unit/util/windows/adsi_spec.rb +135 -41
  218. data/spec/unit/util/windows/sid_spec.rb +0 -10
  219. metadata +48 -2
@@ -33,7 +33,7 @@ module Puppet::Pops::Parser::EppSupport
33
33
  ctx = @lexing_context
34
34
  queue = @token_queue
35
35
 
36
- lex_error "Internal Error: No string or file given to lexer to process." unless scn
36
+ lex_error(Puppet::Pops::Issues::EPP_INTERNAL_ERROR, :error => 'No string or file given to lexer to process.') unless scn
37
37
 
38
38
  ctx[:epp_mode] = :text
39
39
  enqueue_completed([:EPP_START, nil, 0], 0)
@@ -47,7 +47,7 @@ module Puppet::Pops::Parser::EppSupport
47
47
  end
48
48
  end
49
49
  if ctx[:epp_open_position]
50
- lex_error("Unbalanced epp tag, reached <eof> without closing tag.", ctx[:epp_position])
50
+ lex_error(Puppet::Pops::Issues::EPP_UNBALANCED_TAG, {}, ctx[:epp_position])
51
51
  end
52
52
 
53
53
  # Signals end of input
@@ -65,7 +65,9 @@ module Puppet::Pops::Parser::EppSupport
65
65
  case eppscanner.mode
66
66
  when :text
67
67
  # Should be at end of scan, or something is terribly wrong
68
- lex_error("Internal error: template scanner returns text mode and is not and end of input") unless @scanner.eos?
68
+ unless @scanner.eos?
69
+ lex_error(Puppet::Pops::Issues::EPP_INTERNAL_ERROR, :error => 'template scanner returns text mode and is not and end of input')
70
+ end
69
71
  if s
70
72
  # s may be nil if scanned text ends with an epp tag (i.e. no trailing text).
71
73
  enqueue_completed([:RENDER_STRING, s, scn.pos - before], before)
@@ -74,7 +76,7 @@ module Puppet::Pops::Parser::EppSupport
74
76
  # do nothing else, scanner is at the end
75
77
 
76
78
  when :error
77
- lex_error(eppscanner.message())
79
+ lex_error(eppscanner.issue)
78
80
 
79
81
  when :epp
80
82
  # It is meaningless to render empty string segments, and it is harmful to do this at
@@ -97,7 +99,7 @@ module Puppet::Pops::Parser::EppSupport
97
99
  ctx[:epp_mode] = :expr
98
100
  ctx[:epp_open_position] = scn.pos
99
101
  else
100
- lex_error("Internal Error, Unknown mode #{eppscanner.mode} returned by template scanner")
102
+ lex_error(Puppet::Pops::Issues::EPP_INTERNAL_ERROR, :error => "Unknown mode #{eppscanner.mode} returned by template scanner")
101
103
  end
102
104
  nil
103
105
  end
@@ -144,8 +146,8 @@ module Puppet::Pops::Parser::EppSupport
144
146
  #
145
147
  attr_reader :mode
146
148
 
147
- # An error message if `mode == :error`, `nil` otherwise.
148
- attr_reader :message
149
+ # An error issue if `mode == :error`, `nil` otherwise.
150
+ attr_reader :issue
149
151
 
150
152
  # If the first scan should skip leading whitespace (typically detected by the pp lexer when the
151
153
  # pp mode end-token is found (i.e. `-%>`) and then passed on to the scanner.
@@ -159,6 +161,13 @@ module Puppet::Pops::Parser::EppSupport
159
161
  @scanner = scanner
160
162
  end
161
163
 
164
+ # Here for backwards compatibility.
165
+ # @deprecated Use issue instead
166
+ # @return [String] the issue message
167
+ def message
168
+ @issue.nil? ? nil : @issue.format
169
+ end
170
+
162
171
  # Scans from the current position in the configured scanner, advances this scanner's position until the end
163
172
  # of the input, or to the first position after a mode switching token (`<%`, `<%-` or `<%=`). Number of processed
164
173
  # lines and continuation mode can be obtained via {#lines}, and {#mode}.
@@ -189,7 +198,7 @@ module Puppet::Pops::Parser::EppSupport
189
198
  # if s ends with <% then this is an error (unbalanced <% %>)
190
199
  if s.end_with? "<%"
191
200
  @mode = :error
192
- @message = "Unbalanced embedded expression - opening <% and reaching end of input"
201
+ @issue = Puppet::Pops::Issues::EPP_UNBALANCED_EXPRESSION
193
202
  else
194
203
  mode = :epp
195
204
  end
@@ -227,7 +236,7 @@ module Puppet::Pops::Parser::EppSupport
227
236
  # preceded by a % (i.e. skip %%>)
228
237
  part = scanner.scan_until(/[^%]%>/)
229
238
  unless part
230
- @message = "Reaching end after opening <%# without seeing %>"
239
+ @issue = Puppet::Pops::Issues::EPP_UNBALANCED_COMMENT
231
240
  @mode = :error
232
241
  return s
233
242
  end
@@ -20,6 +20,8 @@ class Puppet::Pops::Parser::EvaluatingParser
20
20
  #
21
21
  begin
22
22
  assert_and_report(parser.parse_string(s))
23
+ rescue Puppet::ParseErrorWithIssue => e
24
+ raise e
23
25
  rescue Puppet::ParseError => e
24
26
  # TODO: This is not quite right, why does not the exception have the correct file?
25
27
  e.file = @file_source unless e.file.is_a?(String) && !e.file.empty?
@@ -63,12 +65,16 @@ class Puppet::Pops::Parser::EvaluatingParser
63
65
  end
64
66
 
65
67
  def evaluator
68
+ # Do not use the cached evaluator if this is a migration run
69
+ if (Puppet.lookup(:migration_checker) { nil })
70
+ return Puppet::Pops::Evaluator::EvaluatorImpl.new()
71
+ end
66
72
  @@evaluator ||= Puppet::Pops::Evaluator::EvaluatorImpl.new()
67
73
  @@evaluator
68
74
  end
69
75
 
70
76
  def convert_to_3x(object, scope)
71
- val = @@evaluator.convert(object, scope, nil)
77
+ val = evaluator.convert(object, scope, nil)
72
78
  end
73
79
 
74
80
  def validate(parse_result)
@@ -1,4 +1,5 @@
1
1
  module Puppet::Pops::Parser::HeredocSupport
2
+ include Puppet::Pops::Parser::LexerSupport
2
3
 
3
4
  # Pattern for heredoc `@(endtag[:syntax][/escapes])
4
5
  # Produces groups for endtag (group 1), syntax (group 2), and escapes (group 3)
@@ -14,13 +15,12 @@ module Puppet::Pops::Parser::HeredocSupport
14
15
 
15
16
  # scanner is at position before @(
16
17
  # find end of the heredoc spec
17
- str = scn.scan_until(/\)/) || lexer.lex_error("Unclosed parenthesis after '@(' followed by '#{followed_by}'")
18
+ str = scn.scan_until(/\)/) || lex_error(Puppet::Pops::Issues::HEREDOC_UNCLOSED_PARENTHESIS, :followed_by => followed_by)
18
19
  pos_after_heredoc = scn.pos
19
20
 
20
21
  # Note: allows '+' as separator in syntax, but this needs validation as empty segments are not allowed
21
- unless md = str.match(PATTERN_HEREDOC)
22
- lex_error("Invalid syntax in heredoc expected @(endtag[:syntax][/escapes])")
23
- end
22
+ md = str.match(PATTERN_HEREDOC)
23
+ lex_error(Puppet::Pops::Issues::HEREDOC_INVALID_SYNTAX) unless md
24
24
  endtag = md[1]
25
25
  syntax = md[2] || ''
26
26
  escapes = md[3]
@@ -33,7 +33,7 @@ module Puppet::Pops::Parser::HeredocSupport
33
33
  endtag = $1.strip
34
34
  end
35
35
 
36
- lexer.lex_error("Missing endtag in heredoc") unless endtag.length >= 1
36
+ lex_error(Puppet::Pops::Issues::HEREDOC_MISSING_ENDTAG) unless endtag.length >= 1
37
37
 
38
38
  resulting_escapes = []
39
39
  if escapes
@@ -41,7 +41,7 @@ module Puppet::Pops::Parser::HeredocSupport
41
41
 
42
42
  escapes = escapes.split('')
43
43
  unless escapes.length == escapes.uniq.length
44
- lex_error("An escape char for @() may only appear once. Got '#{escapes.join(', ')}")
44
+ lex_error(Puppet::Pops::Issues::HEREDOC_MULTIPLE_AT_ESCAPES, :escapes => escapes)
45
45
  end
46
46
  resulting_escapes = ["\\"]
47
47
  escapes.each do |e|
@@ -51,7 +51,7 @@ module Puppet::Pops::Parser::HeredocSupport
51
51
  when "L"
52
52
  resulting_escapes += ["\n", "\r\n"]
53
53
  else
54
- lex_error("Invalid heredoc escape char. Only t, r, n, s, u, L, $ allowed. Got '#{e}'")
54
+ lex_error(Puppet::Pops::Issues::HEREDOC_INVALID_ESCAPE, :actual => e)
55
55
  end
56
56
  end
57
57
  end
@@ -66,14 +66,14 @@ module Puppet::Pops::Parser::HeredocSupport
66
66
  if ctx[:newline_jump]
67
67
  scn.pos = ctx[:newline_jump]
68
68
  else
69
- scn.scan_until(/\n/) || lex_error("Heredoc without any following lines of text")
69
+ scn.scan_until(/\n/) || lex_error(Puppet::Pops::Issues::HEREDOC_WITHOUT_TEXT)
70
70
  end
71
71
  # offset 0 for the heredoc, and its line number
72
72
  heredoc_offset = scn.pos
73
73
  heredoc_line = locator.line_for_offset(heredoc_offset)-1
74
74
 
75
75
  # Compute message to emit if there is no end (to make it refer to the opening heredoc position).
76
- eof_message = positioned_message("Heredoc without end-tagged line")
76
+ eof_error = create_lex_error(Puppet::Pops::Issues::HEREDOC_WITHOUT_END_TAGGED_LINE)
77
77
 
78
78
  # Text from this position (+ lexing contexts offset for any preceding heredoc) is heredoc until a line
79
79
  # that terminates the heredoc is found.
@@ -82,7 +82,8 @@ module Puppet::Pops::Parser::HeredocSupport
82
82
  endline_pattern = /([[:blank:]]*)(?:([|])[[:blank:]]*)?(?:(\-)[[:blank:]]*)?#{Regexp.escape(endtag)}[[:blank:]]*\r?(?:\n|\z)/
83
83
  lines = []
84
84
  while !scn.eos? do
85
- one_line = scn.scan_until(/(?:\n|\z)/) || lexer.lex_error_without_pos(eof_message)
85
+ one_line = scn.scan_until(/(?:\n|\z)/)
86
+ raise eof_error unless one_line
86
87
  if md = one_line.match(endline_pattern)
87
88
  leading = md[1]
88
89
  has_margin = md[2] == '|'
@@ -116,7 +117,7 @@ module Puppet::Pops::Parser::HeredocSupport
116
117
  lines << one_line
117
118
  end
118
119
  end
119
- lex_error_without_pos(eof_message)
120
+ raise eof_error
120
121
  end
121
122
 
122
123
  # Produces the heredoc text string given the individual (unprocessed) lines as an array.
@@ -193,9 +193,15 @@ module Puppet::Pops::Parser::InterpolationSupport
193
193
  token_name = token[0]
194
194
  ctx[:after] = token_name
195
195
  if token_name == :RBRACE && ctx[:brace_count] == brace_count
196
- if queue.size - queue_size == 1
196
+ qlength = queue.size - queue_size
197
+ if qlength == 1
197
198
  # Single token is subject to replacement
198
199
  queue[-1] = transform_to_variable(queue[-1])
200
+ elsif qlength > 1 && [:DOT, :LBRACK].include?(queue[queue_size + 1][0])
201
+ # A first word, number of name token followed by '[' or '.' is subject to replacement
202
+ # But not for other operators such as ?, +, - etc. where user must use a $ before the name
203
+ # to get a variable
204
+ queue[queue_size] = transform_to_variable(queue[queue_size])
199
205
  end
200
206
  return
201
207
  end
@@ -214,7 +214,7 @@ class Puppet::Pops::Parser::Lexer2
214
214
  @scanner = StringScanner.new(string)
215
215
  @locator = locator || Puppet::Pops::Parser::Locator.locator(string, '')
216
216
  @lexing_context[:escapes] = escapes || UQ_ESCAPES
217
- @lexing_context[:uq_slurp_pattern] = (interpolate || !escapes.empty?) ? SLURP_UQ_PATTERN : SLURP_ALL_PATTERN
217
+ @lexing_context[:uq_slurp_pattern] = interpolate ? (escapes.include?('$') ? SLURP_UQ_PATTERN : SLURP_UQNE_PATTERN) : SLURP_ALL_PATTERN
218
218
  end
219
219
 
220
220
  # Convenience method, and for compatibility with older lexer. Use the lex_file instead.
@@ -275,7 +275,7 @@ class Puppet::Pops::Parser::Lexer2
275
275
  ctx = @lexing_context
276
276
  queue = @token_queue
277
277
 
278
- lex_error_without_pos("Internal Error: No string or file given to lexer to process.") unless scn
278
+ lex_error_without_pos(Puppet::Pops::Issues::NO_INPUT_TO_LEXER) unless scn
279
279
 
280
280
  scn.skip(PATTERN_WS)
281
281
 
@@ -527,13 +527,13 @@ class Puppet::Pops::Parser::Lexer2
527
527
  if la2 >= 'A' && la2 <= 'Z'
528
528
  # CLASSREF or error
529
529
  value = scn.scan(PATTERN_CLASSREF)
530
- if value
530
+ if value && scn.peek(2) != '::'
531
531
  after = scn.pos
532
532
  emit_completed([:CLASSREF, value.freeze, after-before], before)
533
533
  else
534
534
  # move to faulty position ('::<uc-letter>' was ok)
535
535
  scn.pos = scn.pos + 3
536
- lex_error("Illegal fully qualified class reference")
536
+ lex_error(Puppet::Pops::Issues::ILLEGAL_FULLY_QUALIFIED_CLASS_REFERENCE)
537
537
  end
538
538
  else
539
539
  value = scn.scan(PATTERN_BARE_WORD)
@@ -546,7 +546,7 @@ class Puppet::Pops::Parser::Lexer2
546
546
  else
547
547
  # move to faulty position ('::' was ok)
548
548
  scn.pos = scn.pos + 2
549
- lex_error("Illegal fully qualified name")
549
+ lex_error(Puppet::Pops::Issues::ILLEGAL_FULLY_QUALIFIED_NAME)
550
550
  end
551
551
  end
552
552
  else
@@ -573,13 +573,30 @@ class Puppet::Pops::Parser::Lexer2
573
573
  value = scn.scan(PATTERN_NUMBER)
574
574
  if value
575
575
  length = scn.pos - before
576
- assert_numeric(value, length)
576
+ assert_numeric(value, before)
577
577
  emit_completed([:NUMBER, value.freeze, length], before)
578
578
  else
579
- # move to faulty position ([0-9] was ok)
580
579
  invalid_number = scn.scan_until(PATTERN_NON_WS)
580
+ if before > 1
581
+ after = scn.pos
582
+ scn.pos = before - 1
583
+ if scn.peek(1) == '.'
584
+ # preceded by a dot. Is this a bad decimal number then?
585
+ scn.pos = before - 2
586
+ while scn.peek(1) =~ /^\d$/
587
+ invalid_number = nil
588
+ before = scn.pos
589
+ break if before == 0
590
+ scn.pos = scn.pos - 1
591
+ end
592
+ end
593
+ scn.pos = before
594
+ invalid_number = scn.peek(after - before) unless invalid_number
595
+ end
596
+ length = scn.pos - before
597
+ assert_numeric(invalid_number, before)
581
598
  scn.pos = before + 1
582
- lex_error("Illegal number '#{invalid_number}'")
599
+ lex_error(Puppet::Pops::Issues::ILLEGAL_NUMBER, {:value => invalid_number})
583
600
  end
584
601
 
585
602
  when 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
@@ -595,21 +612,21 @@ class Puppet::Pops::Parser::Lexer2
595
612
  scn.pos = scn.pos + 1
596
613
  fully_qualified = scn.match?(/::/)
597
614
  if fully_qualified
598
- lex_error("Illegal fully qualified name")
615
+ lex_error(Puppet::Pops::Issues::ILLEGAL_FULLY_QUALIFIED_NAME)
599
616
  else
600
- lex_error("Illegal name or bare word")
617
+ lex_error(Puppet::Pops::Issues::ILLEGAL_NAME_OR_BARE_WORD)
601
618
  end
602
619
  end
603
620
 
604
621
  when 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
605
622
  'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
606
623
  value = scn.scan(PATTERN_CLASSREF)
607
- if value
624
+ if value && scn.peek(2) != '::'
608
625
  emit_completed([:CLASSREF, value.freeze, scn.pos - before], before)
609
626
  else
610
627
  # move to faulty position ([A-Z] was ok)
611
628
  scn.pos = scn.pos + 1
612
- lex_error("Illegal class reference")
629
+ lex_error(Puppet::Pops::Issues::ILLEGAL_CLASS_REFERENCE)
613
630
  end
614
631
 
615
632
  when "\n"
@@ -3,18 +3,6 @@
3
3
  #
4
4
  module Puppet::Pops::Parser::LexerSupport
5
5
 
6
- # Formats given message by appending file, line and position if available.
7
- def positioned_message(msg, pos = nil)
8
- result = [msg]
9
- file = @locator.file
10
- line = @locator.line_for_offset(pos || @scanner.pos)
11
- pos = @locator.pos_on_line(pos || @scanner.pos)
12
-
13
- result << "in file #{file}" if file && file.is_a?(String) && !file.empty?
14
- result << "at line #{line}:#{pos}"
15
- result.join(" ")
16
- end
17
-
18
6
  # Returns "<eof>" if at end of input, else the following 5 characters with \n \r \t escaped
19
7
  def followed_by
20
8
  return "<eof>" if @scanner.eos?
@@ -35,27 +23,68 @@ module Puppet::Pops::Parser::LexerSupport
35
23
  end
36
24
 
37
25
  # Raises a Puppet::LexError with the given message
38
- def lex_error_without_pos msg
39
- raise Puppet::LexError.new(msg)
26
+ def lex_error_without_pos(issue, args = {})
27
+ raise Puppet::ParseErrorWithIssue.new(issue.format(args), nil, nil, nil, nil, issue.issue_code)
40
28
  end
41
29
 
42
- # Raises a Puppet::LexError with the given message
43
- def lex_error(msg, pos=nil)
44
- raise Puppet::LexError.new(positioned_message(msg, pos))
30
+ # Raises a Puppet::ParserErrorWithIssue with the given issue and arguments
31
+ def lex_error(issue, args = {}, pos=nil)
32
+ raise create_lex_error(issue, args, pos)
33
+ end
34
+
35
+ def filename
36
+ file = @locator.file
37
+ file.is_a?(String) && !file.empty? ? file : nil
38
+ end
39
+
40
+ def line(pos)
41
+ @locator.line_for_offset(pos || @scanner.pos)
42
+ end
43
+
44
+ def position(pos)
45
+ @locator.pos_on_line(pos || @scanner.pos)
46
+ end
47
+
48
+ def lex_warning(issue, args = {}, pos=nil)
49
+ Puppet::Util::Log.create({
50
+ :level => :warning,
51
+ :message => issue.format(args),
52
+ :issue_code => issue.issue_code,
53
+ :file => filename,
54
+ :line => line(pos),
55
+ :pos => position(pos),
56
+ })
57
+ end
58
+
59
+ # @param issue [Puppet::Pops::Issues::Issue] the issue
60
+ # @param args [Hash<Symbol,String>] Issue arguments
61
+ # @param pos [Integer]
62
+ # @return [Puppet::ParseErrorWithIssue] the created error
63
+ def create_lex_error(issue, args = {}, pos = nil)
64
+ Puppet::ParseErrorWithIssue.new(
65
+ issue.format(args),
66
+ filename,
67
+ line(pos),
68
+ position(pos),
69
+ nil,
70
+ issue.issue_code)
45
71
  end
46
72
 
47
73
  # Asserts that the given string value is a float, or an integer in decimal, octal or hex form.
48
74
  # An error is raised if the given value does not comply.
49
75
  #
50
- def assert_numeric(value, length)
51
- if value =~ /^0[xX].*$/
52
- lex_error("Not a valid hex number #{value}", length) unless value =~ /^0[xX][0-9A-Fa-f]+$/
76
+ def assert_numeric(value, pos)
77
+ if value =~ /^0[xX]/
78
+ lex_error(Puppet::Pops::Issues::INVALID_HEX_NUMBER, {:value => value}, pos) unless value =~ /^0[xX][0-9A-Fa-f]+$/
79
+
80
+ elsif value =~ /^0[^.]/
81
+ lex_error(Puppet::Pops::Issues::INVALID_OCTAL_NUMBER, {:value => value}, pos) unless value =~ /^0[0-7]+$/
53
82
 
54
- elsif value =~ /^0[^.].*$/
55
- lex_error("Not a valid octal number #{value}", length) unless value =~ /^0[0-7]+$/
83
+ elsif value =~ /^\d+[eE.]/
84
+ lex_error(Puppet::Pops::Issues::INVALID_DECIMAL_NUMBER, {:value => value}, pos) unless value =~ /^\d+(?:\.\d+)?(?:[eE]-?\d+)?$/
56
85
 
57
86
  else
58
- lex_error("Not a valid decimal number #{value}", length) unless value =~ /0?\d+(?:\.\d+)?(?:[eE]-?\d+)?/
87
+ lex_error(Puppet::Pops::Issues::ILLEGAL_NUMBER, {:value => value}, pos) unless value =~ /^\d+$/
59
88
  end
60
89
  end
61
90
 
@@ -93,11 +93,8 @@ class Puppet::Pops::Parser::Parser
93
93
  else
94
94
  value_at = "'#{value[:value]}'"
95
95
  end
96
- if @yydebug
97
- error = "Syntax error at #{value_at}, token: #{token}"
98
- else
99
- error = "Syntax error at #{value_at}"
100
- end
96
+ error = Puppet::Pops::Issues::SYNTAX_ERROR.format(:where => value_at)
97
+ error = "#{error}, token: #{token}" if @yydebug
101
98
 
102
99
  # Note, old parser had processing of "expected token here" - do not try to reinstate:
103
100
  # The 'expected' is only of value at end of input, otherwise any parse error involving a
@@ -110,19 +107,19 @@ class Puppet::Pops::Parser::Parser
110
107
  # must be handled by the grammar. The lexer may have enqueued tokens far ahead - the lexer's opinion about this
111
108
  # is not trustworthy.
112
109
  #
113
-
114
- except = Puppet::ParseError.new(error)
110
+ file = nil
111
+ line = nil
112
+ pos = nil
115
113
  if token != 0
116
- path = value[:file]
117
- except.line = value[:line]
118
- except.pos = value[:pos]
114
+ file = value[:file]
115
+ line = value[:line]
116
+ pos = value[:pos]
119
117
  else
120
118
  # At end of input, use what the lexer thinks is the source file
121
- path = lexer.file
119
+ file = lexer.file
122
120
  end
123
- except.file = path if path.is_a?(String) && !path.empty?
124
-
125
- raise except
121
+ file = nil unless file.is_a?(String) && !file.empty?
122
+ raise Puppet::ParseErrorWithIssue.new(error, file, line, pos, nil, issue_code = Puppet::Pops::Issues::SYNTAX_ERROR.issue_code)
126
123
  end
127
124
 
128
125
  # Parses a String of pp DSL code.