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

@NamedVariant self referential default values are not correctly resolved

Agile BoardAttach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.5.16, 3.0.10, 4.0.1
    • 4.0.2
    • None

    Description

      If a default parameter refers to another parameter ( String language = 'java', String extension = language ) it will fail, when the named variant is used.

      import groovy.transform.NamedVariant
      import spock.lang.Specification
      
      class Demo {
          @NamedVariant
          String fileInSourceSet(String language = 'java', String extension = language) {
              return "$language -> .$extension"
          }
          
          def test() {
      		assert fileInSourceSet() == 'java -> .java'
      		assert fileInSourceSet('groovy') == 'groovy -> .groovy'
      		assert fileInSourceSet(language: 'kotlin', extension: 'kt') == 'kotlin -> .kt'
              // fails
      		assert fileInSourceSet(language: 'groovy') == 'groovy -> .groovy'
          }
          
          static main(args) {
                  new Demo().test() 
          }    
      }
      

      See on WebConsole (as long as deployed version is 3.0.10)

      groovy.lang.MissingPropertyException: No such property: language for class: Demo
      	at Demo.fileInSourceSet(Script1.groovy)
      	at Demo$fileInSourceSet$2.callCurrent(Unknown Source)
      	at Demo.test(Script1.groovy:14)
      	at Demo$test.call(Unknown Source)
      	at Demo.main(Script1.groovy:18)
      

      It generates

      @groovy.transform.Generated
          public java.lang.String fileInSourceSet(@groovy.transform.NamedParams(value = [@groovy.transform.NamedParam(value = 'language', type = java.lang.String, required = false), @groovy.transform.NamedParam(value = 'extension', type = java.lang.String, required = false)]) java.util.Map namedArgs) {
              if ( namedArgs == null) {
                  throw new java.lang.IllegalArgumentException('Named parameter map cannot be null')
              }
              for (java.lang.String namedArgKey : namedArgs.keySet()) {
                  assert ['language', 'extension'].contains( namedArgKey ) : 'Unrecognized namedArgKey: ' + namedArgKey }
              return this.fileInSourceSet(namedArgs.containsKey('language') ? namedArgs.language : 'java', namedArgs.containsKey('extension') ? namedArgs.extension : language )
          }

      The problematic line is namedArgs.containsKey('extension') ? namedArgs.extension : language which either would have to duplicate the logic for {{language}} or use a local variable for it.

      Relates to GROOVY-10261

      Attachments

        Issue Links

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            paulk Paul King
            leonard84 Leonard Brünings
            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 - 1h
              1h

              Slack

                Issue deployment