Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-9183

Issue using @MapConstructor and @NamedVariant

    XMLWordPrintableJSON

Details

    Description

      I have a static method marked with @NamedVariant, that takes a "Configuration" object as a parameter, which is marked with @NamedDelegate. The "Configuration" object is defined as a static inner class marked with @Immutable.
       
      My Class:

      class CsvRowMapper {
          private final Settings settings
          @NamedVariant
          CsvRowMapper(Settings settings) {
              this.settings = settings
          }
          @NamedVariant
          static CsvRowMapper parse(@NamedDelegate Settings settings, Reader reader) {
              new CsvRowMapper(settings).parse(reader)
          }
          CsvRowMapper parse(Reader source) {
              // do work here
              return this
          }
          @Immutable
          static class Settings {
              String separator = ','
              boolean headers = true
              int headersRow = 0
              int firstDataRow = 1
          }
      }

       
      I've highlighted the important parts. The issue is when I use this class like:

      CsvRowMapper.parse(*separator: '\t'*, tsvFileReader)
      

       
      I get an GroovyCastException because it's trying to set headersRow or firstDataRow to null:
       

      org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '\{separator= , headers=null, headersRow=null, firstDataRow=null}'
        with class 'java.util.LinkedHashMap' to class 'CsvRowMapper$Settings'
        due to: org.codehaus.groovy.runtime.typehandling.GroovyCastException:
          Cannot cast object 'null' with class 'null' to class 'int'. Try 'java.lang.Integer' instead
      

       
      Even though there are default values for each setting.
       
      I loaded up this into GroovyConsole, and I think the issue is that the @NameVariant version of the `parse` method is creating a map with ALL keys for the @NamedDelegate Settings class (See NamedVariant.png).
       
      Furthermore the @Immutable annotation adds @MapConstructor to my Settings class, which only checks if the given map contains the `key`, not also if it has a `value` (See MapConstructor.png).
       
      The @NamedVariant passes a map containing null values for all keys not supplied during method execution, and @MapConstructor only checks if the given map has the key, not a value.
       

      Attachments

        1. NamedVariant.png
          92 kB
          Eric Berry
        2. MapConstructor.png
          157 kB
          Eric Berry

        Issue Links

          Activity

            People

              emilles Eric Milles
              townsfolk Eric Berry
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0h
                  0h
                  Logged:
                  Time Spent - 40m
                  40m