Java 类型别名的注解处理器

Java annotation processor for type aliases

从我记事起,我就一直怀念 Java 中的类型别名(例如 c++ 中的 typedef 或 haskell 中的 type/newtype)。

在Android SDK中,我们得到了support annotations,其中包括@IntDef@StringDef和各种资源类型注释,这有助于我们找出可能的误用integer/string 编译时的值。我从 Android 文档中插入一段代码来给你一个简短的想法:

@IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
@Retention(RetentionPolicy.SOURCE)
public @interface NavigationMode {}

public static final int NAVIGATION_MODE_STANDARD = 0;
public static final int NAVIGATION_MODE_LIST = 1;
public static final int NAVIGATION_MODE_TABS = 2;

@NavigationMode
public abstract int getNavigationMode();

public abstract void setNavigationMode(@NavigationMode int mode);

实际上,95% 的情况我想要类型别名都是相同的:当我得到某种数据库行 ID,通常是 longString,这导致必须对类型进行编码有关名称中变量的信息(例如 long folderIdlong messageId)。然而,StringDef/IntDef注解有一个烦人的限制:由于某种原因,它们需要一组预定义的常量,所以你只能描述一组有限的值,这显然是不够的数据库标识符。

我想要的是某种类似的注释 @TypeAlias 和 Lint 检查,所以我可以这样做:

@TypeAlias
@Retention(RetentionPolicy.SOURCE)
public @interface FolderId { }

@FolderId
public long getFolderIdByName(Database db, String name) {
    long id = db.foldersTable().findByName(name).getId();
    return id;
    /*
      we might need to suppress the check here
      (because we pass long as a @FolderId long),
      but that's okay, since we are aware of
      what we are doing here, and it's the only
      possible injection point for @FolderId
    */
}

public void deleteMessagesIn(Database db, @FolderId long folder) {
   // whatever
}

public void deleteMessagesInInbox(Database db) {
    deleteMessagesIn(db, 1); // rejected by Lint, trying to pass long as @FolderId long
    deleteMessagesIn(db, getFolderIdByName(db, "Inbox")); // ok, passes Lint check
}

我看不出有什么好的理由将类型别名注释限制为一组有限值,我们可以像上面提到的那样通过抑制来解决它,或者可能通过专门为提供类型的函数引入另一个注释别名。

更重要的是,这不仅仅是关于 Android 注释的限制:任何普通的 Java 应用程序也可以从这些类型的别名中受益,而我没有设法做到google 任何类似的东西。我们还可以从使用 TYPE_PARAMETER 目标中获益,这将使它看起来几乎像真实的类型别名。

所以问题是:

P.S。 @mernst 向我指出了 Checker 框架,我设法以一种相对轻松的方式将它与 Android 集成:https://github.com/karlicoss/checker-fenum-android-demo

检查类型别名 (typedef) 是否正确使用的静态分析器是 Fake Enum Checker that is distributed with the Checker Framework。它已被用于查找 Swing 和 JabRef 中的错误。