如何创建自定义 Intellij 模板 setter 以与 Guava 的 Optional 一起使用

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

我正在尝试使用 Intelij 模板编写自定义 setter,但用于 Google 的 Guava Optionals。例如,如果我有一个 class 如下:

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

在 Android Studio 输出中使用默认 Setter 生成:

public class Note {
    public Optional<String> title;

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

我要实现的是:

public class Note {
    public Optional<String> title;

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

到目前为止我尝试的是复制 Intelij 的模板并使用 StringUtil.split() 去除方法签名的 Optional< 部分。但是,我在使用下面的模板时遇到错误。

错误

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

对我应该做什么有什么建议吗?

Setter 代

的默认 Intelij Default 模板
#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;
}

我自定义的 Guava Optional Setter 代

#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;
}

经过一些搜索,我发现在 StringUtils 中,split() 的签名与上面发布的签名不同。

我能够编写一个完整的解决方案来为下面的 Guava Optionals 创建 setter。它非常脆弱,因为我是 IntelliJ 中模板的新手,因为它依赖于包名称 com.google.common.base.Optional 以及似乎没有正式记录的 StringsUtils

它首先检查 $paramName 是否是一个包装的 Optional。如果是这样,请使用 Guava 可选设置完成 setter。否则,回退到默认的 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;
}

已编辑 代码基于@ChiefTwoPencils 的反馈。

我看到了你的回答,这很好,但你必须知道你不必为你需要的每种类型使用条件使模板复杂化(即使你现在只有一个;下次怎么样?)。

相反,为什么不为这个特定需求创建自己的方法并选择何时创建方法?

我会第一个承认这可以做得更好;我只是想看看我是否能让它正常工作。尽管如此,它并不依赖于 Optional 的完全限定包名称;我什至没有安装 Guava 也能正常工作。

#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);
}

Getter,在我的例子中,我需要大写字母的第一个字母并删除字段变量

的'm'
#if($field.modifierStatic)
static ##
#end
$field.type ##
#if($field.recordComponent)
  ${field.name}##
#else
#set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project))))
#if ($StringUtil.startsWithIgnoreCase($name, 'm'))
  #set($name = $name.substring(1, $name.length()))
#end
#if ($field.boolean && $field.primitive)
  Is##
#else
  Get##
#end  
${name}##
#end
() {
  return $field.name;
}

同setter一样,去掉字段变量的'm',param也去掉,首字母小写

#set($paramName = $helper.getParamName($field, $project))
#if($field.modifierStatic)
static ##
#end
#set($functionName = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field, $project))))
#if ($StringUtil.startsWithIgnoreCase($paramName, 'm'))
  #set($paramName = $paramName.substring(1,2).toLowerCase() + $paramName.substring(2, $paramName.length()))
  #set($functionName = $functionName.substring(1)) 
#end
void Set$functionName ($field.type $paramName) {
  #if ($field.name == $paramName)
    #if (!$field.modifierStatic)
      this.##
    #else
      $classname.##
    #end
  #end
  $field.name = $paramName;
}

示例:

private Handler mJobHandler;

Getter:

public Handler GetJobHandler()
{
    return mJobHandler;
}

Setter:

public void SetJobHandler(Handler jobHandler)
{
    mJobHandler = jobHandler;
}