【问题标题】:Java annotation processor for type aliases用于类型别名的 Java 注释处理器
【发布时间】:2017-01-05 09:12:57
【问题描述】:

只要我记得,我就一直错过 Java 中的类型别名(例如 c++ 中的 typedef 或 haskell 中的 type/newtype)。

在 Android SDK 中,我们有 support annotations,其中包括 @IntDef@StringDef 和各种资源类型注释,这有助于我们在编译时找出可能的整数/字符串值滥用。我正在插入一段来自 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 注解有一个恼人的限制:由于某种原因,它们需要一组预定义的常量,因此您只能描述一组有限的值,这对于 DB 标识符显然是不够的。

我想要的是某种类似的注释,比如 @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 应用程序也可以从这些类型的别名中受益,而且我没有设法在谷歌上搜索到任何类似的东西。我们还可以从使用TYPE_PARAMETER 目标中受益,这将使所有目标看起来几乎就像真正的类型别名。

所以问题是:

  • 是否有执行此类检查的静态分析器?
  • 如果没有,是否有任何我遗漏的基本限制阻碍了它的实施?从那以后,我觉得这很有用,所以如果没有的话,有人会这样做的。

附: @mernst 向我介绍了 Checker 框架,我设法以一种相对轻松的方式将其与 Android 集成:https://github.com/karlicoss/checker-fenum-android-demo

【问题讨论】:

    标签: java android types annotations type-alias


    【解决方案1】:

    检查类型别名 (typedef) 是否正确使用的静态分析器是 Fake Enum Checker,它与 Checker Framework 一起分发。它已被用于查找 Swing 和 JabRef 中的错误。

    【讨论】:

    • 非常感谢!没有我想象的那么方便,但我让它适用于 Android 项目,太棒了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多