From 1bd5fe50725a16cb17634d54572751efbde0bab7 Mon Sep 17 00:00:00 2001 From: Evgeni Golov Date: Fri, 10 Nov 2023 10:59:08 +0100 Subject: [PATCH] Fixes #36912 - support multi-line type definitions This strips line breaks from type definitions, thus making them parseable again. This will probably horribly break if type manifests would contain anything else but type definitions, but Puppet recommends [1] to store them in separate files and only have one type alias per file. [1] https://www.puppet.com/docs/puppet/7/lang_type_aliases --- lib/kafo/data_type_parser.rb | 21 +++++++++++++++++++-- test/kafo/data_type_parser_test.rb | 24 ++++++++++++++++++++++++ test/kafo/data_type_test.rb | 5 +++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/lib/kafo/data_type_parser.rb b/lib/kafo/data_type_parser.rb index d016738f..f790c60e 100644 --- a/lib/kafo/data_type_parser.rb +++ b/lib/kafo/data_type_parser.rb @@ -8,9 +8,26 @@ class DataTypeParser def initialize(manifest) @logger = KafoConfigure.logger - @types = {} + + lines = [] + type_line_without_newlines = +'' manifest.each_line do |line| - if (type = TYPE_DEFINITION.match(line.force_encoding("UTF-8"))) + line = line.force_encoding("UTF-8").strip + next if line.start_with?('#') + + line = line.split(' #').first.strip + if line =~ TYPE_DEFINITION + lines << type_line_without_newlines + type_line_without_newlines = line + else + type_line_without_newlines << line + end + end + lines << type_line_without_newlines + + @types = {} + lines.each do |line| + if (type = TYPE_DEFINITION.match(line)) @types[type[1]] = type[2] end end diff --git a/test/kafo/data_type_parser_test.rb b/test/kafo/data_type_parser_test.rb index 861d51c3..cdb32ba3 100644 --- a/test/kafo/data_type_parser_test.rb +++ b/test/kafo/data_type_parser_test.rb @@ -24,6 +24,30 @@ module Kafo it { _(parser.types).must_equal({'Ipv4' => 'Pattern[/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/]'}) } end + describe "parse pattern with a hash inside" do + let (:file) do + <<~'PUPPET' + type Stdlib::Email = Pattern[/\A[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/] + PUPPET + end + it { _(parser.types).must_equal({"Stdlib::Email"=>"Pattern[/\\A[a-zA-Z0-9.!\#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\\z/]"}) } + end + + describe "parse multiline alias" do + let(:file) { "type IP = Variant[\n IPv4,\n IPv6,\n]" } + it { _(parser.types).must_equal({'IP' => 'Variant[IPv4,IPv6,]'}) } + end + + describe "parse multiline alias with EOL comment" do + let(:file) { "type IP = Variant[\n IPv4, # Legacy IP\n IPv6,\n]" } + it { _(parser.types).must_equal({'IP' => 'Variant[IPv4,IPv6,]'}) } + end + + describe "parse multiple multiline aliases" do + let(:file) { "# We need IP\ntype IP = Variant[\n IPv4, # Legacy IP\n IPv6,\n]\n# We also need IPProto\ntype IPProto = Variant[\n TCP,\n UDP,\n]" } + it { _(parser.types).must_equal({"IP"=>"Variant[IPv4,IPv6,]", "IPProto"=>"Variant[TCP,UDP,]"}) } + end + describe "#register" do after { DataType.unregister_type('Test') } let(:file) { 'type Test = String' } diff --git a/test/kafo/data_type_test.rb b/test/kafo/data_type_test.rb index 896ba873..4d7c3164 100644 --- a/test/kafo/data_type_test.rb +++ b/test/kafo/data_type_test.rb @@ -62,6 +62,11 @@ module Kafo _(DataType.new_from_string('Example[1,Float, /(regexp)/, Enum["foo", \'bar\'],-2]')).must_equal 'instance' end + it 'instantiates type with trailing comma' do + data_type.expect(:new, 'instance', ['1', 'Float']) + _(DataType.new_from_string('Example[1,Float,]')).must_equal 'instance' + end + it 'instantiates type with multiple nested arguments' do data_type.expect(:new, 'instance', ['Hash[String, String]', 'Hash[String, String]']) _(DataType.new_from_string('Example[Hash[String, String], Hash[String, String]]')).must_equal 'instance'