Search code examples
javaandroidtemplatesintellij-ideaguava

How to create a custom Intellij template setter for use with Guava's Optional


I am trying to write a custom setter using Intelij Template's but for Google's Guava Optionals. For example if I have a class as follows:

public class Note {
    public Optional<String> title;
}

Using the default Setter generation in Android Studio outputs:

public class Note {
    public Optional<String> title;

    public void setTitle(Optional<String> title) {
        this.title = title;
    } 
}

What I want to achieve is:

public class Note {
    public Optional<String> title;

    public void setTitle(String title) {
        this.title = Optional.fromNullable(title);
    } 
}

What I have tried so far is copying Intelij's Template and using StringUtil.split() to strip the Optional< part of the method signature. However I'm getting an error while I'm using the template below.

Error

Incorrect method 'public void setTitle($StringUtil.split($field.type, true, "<").get(1) title) { mTitle = title; }

Any advice on what I should do?

Default Intelij Default Template for Setter Generation

#set($paramName = $helper.getParamName($field, $project))
public ##
#if($field.modifierStatic)
  static ##
#end
void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($field.type $paramName) {
  #if ($field.name == $paramName)
    #if (!$field.modifierStatic)
      this.##
    #else
      $classname.##
    #end
  #end
  $field.name = $paramName;
}

My custom Guava Optional Setter Generation

#set($paramName = $helper.getParamName($field, $project))
public ##
#if($field.modifierStatic)
  static ##
#end
void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($StringUtil.split($field.type, true, "<").get(1) $paramName) {
  #if ($field.name == $paramName)
    #if (!$field.modifierStatic)
      this.##
    #else
      $classname.##
    #end
  #end
  $field.name = $paramName;
}

Solution

  • After some searching I found that in StringUtils, split() had a different signature than as posted above.

    I was able to write a complete solution to create a setter for Guava Optionals below. It is quite fragile as I am new to templates in IntelliJ, as it relies on the package name com.google.common.base.Optional and also on the StringsUtils that doesn't seem to be documented officially.

    It first checks if the $paramName is a wrapped Optional. If so, complete the setter with Guava optional setting. Otherwise, fallback to the default IntelliJ setter.

    #set($paramName = $helper.getParamName($field, $project))
    public ##
    #if($field.modifierStatic)
        static ##
    #end
    #if($StringUtil.split($field.type, "<").get(0).equals("com.google.common.base.Optional"))    
        #set($paramSignature = $StringUtil.trimEnd($StringUtil.substringAfter($field.type, "<"), ">"))
        #set($fieldAssignment = "Optional.fromNullable(" + $paramName + ")") 
    #else
        #set($paramSignature = $field.type)
        #set($fieldAssignment = $paramName)
    #end
    void set$StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project)))($paramSignature $paramName) { 
    #if ($field.name == $paramName)
        #if (!$field.modifierStatic)
            this.##
        #else
            $classname.##
        #end
    #end
    $field.name = $fieldAssignment;
    }
    

    EDITED Code based on feedback from @ChiefTwoPencils.