【问题标题】:Scala: Custom compiler warningScala:自定义编译器警告
【发布时间】:2014-04-12 15:46:01
【问题描述】:

我创建了一个带有一些抽象过程的特征(方法返回 Unit)。然后,为了方便开发,我创建了一个子特征,将其放入虚拟实现 {} 中。但是我想在虚拟特征上发出编译器警告:“使用虚拟特征可能无法实现所有功能。在生产中使用基本特征。”

我查看了 Scala 注释和 Java 注释,但找不到合适的注释或执行此操作的方法。我可以只使用一个已弃用的注释,但这很不雅:

@deprecated("GraphicMethodsDummy contains procedure stubs. Inherit from GraphicMethods for production", "")

从 deprecated 继承似乎没有太大优势,因为生成编译器消息的方法似乎是私有的并且不能被覆盖。

【问题讨论】:

    标签: java scala annotations


    【解决方案1】:
    1. 更改您的 API,以便只能通过“创建者”方法(例如在伴随对象中)获得虚拟特征。
    2. 将“创建者方法”实现为a def macro它看起来像这样:

    class Dummy
    
    object creator {
        def apply(): Dummy = macro creatorImpl
    
        def creatorImpl(c: Context)(): c.Expr[Dummy] = {
            import c.universe._
    
            c.warning(c.enclosingPosition,
                """Using the dummy trait all functionality may not be implemented. 
                            Use the base trait in production.""")
    
            reify(new Dummy)
        }
    }
    

    请注意,在各种 API(如 Guava)中常用的另一种较少涉及的方法是向您的类添加自定义注释(例如 @NotSafeForProd)。但是,这当然不会产生编译器警告。

    【讨论】:

      【解决方案2】:

      如果定期弃用还不够好,那么自行滚动如何:

      package scala {
        class noProd extends deprecatedInheritance("Provide an impl for production", since="forever")
      }
      
      package dummyonly {
      
        trait Abs { def f(i: Int): String }
      
        @noProd
        class Dummy extends Abs {
          def f(i: Int) = i.toString
        }
      }
      

      在单独的编译单元中:

      //dummyonly2.scala:3: warning: inheritance from class Dummy in package dummyonly is deprecated: Provide an impl for production
      
      package dummyonly {
        class Mine extends Dummy
      }
      

      编辑:

      特权注释是 scala 私有的,但它非常有用,将其隐藏在蒲式耳之下是犯罪行为。

      我真的不知道,但代码注释如下:

      // for now, this needs to be generalized to communicate other modifier deltas
      

      或者,换个说法,WTF?我知道什么是“修饰符”,但“修饰符增量”超出了我的理解范围。不过,评论表明,当他们弄清楚如何使其以可维护的方式工作时,注释可能会看到更广泛的访问权限。

      我认为应该使用分号而不是逗号,即“for now; ...”,但 Scala 程序员被编程为避免使用分号,即使语法正确,他们也会避免使用分号。

      【讨论】:

      • 虽然在内部可以说有点“hacky”,但这个解决方案对于最终用户来说更具可读性并且总体上比宏更好;也就是说,如果使用模式符合 OP 所追求的,并且如果它是一种临时措施(因为您实际上是在使用未记录的内部 API)。答案将受益于解释为什么会有 scala 包声明。
      • @TheTerribleSwiftTomato 添加了元注释。我同意,我不确定 OP 想要什么,所以我编造了一些东西。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 2014-06-10
      • 1970-01-01
      • 2011-05-09
      • 2020-05-15
      • 2011-09-28
      相关资源
      最近更新 更多