Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 860
Marvin Bernal Avatar asked Feb 20 '16 22:02

Marvin Bernal


2 Answers

I see your answer, and that's nice, but you must know you don't have to complicate the template with conditionals for each type you need (even though you only have one now; what about next time?).

Instead, why not create your own for this specific need and choose when you go to create the methods?

I'll be the first to admit this could be done a little nicer; I was just trying to see if I could get it to work right. Nonetheless, it's not dependent on the fully qualified package name of Optional; I don't even have Guava installed and it works.

#set($paramName = $helper.getParamName($field, $project))
public ##
#if($field.modifierStatic)
  static ##
#end
void set$StringUtil.capitalizeWithJavaBeanConvention(
  $StringUtil.sanitizeJavaIdentifier(
    $helper.getPropertyName($field, $project)
  )
)($StringUtil.trimEnd($StringUtil.substringAfter($field.type, "<"), ">") $paramName) {
  #if ($field.name == $paramName)
    #if (!$field.modifierStatic)
      this.##
    #else
      $classname.##
    #end
  #end
  $field.name = Optional.fromNullable($paramName);
}
like image 178
ChiefTwoPencils Avatar answered Sep 22 '22 04:09

ChiefTwoPencils


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.

like image 34
Marvin Bernal Avatar answered Sep 24 '22 04:09

Marvin Bernal