Scala, Maven, and preprocessors

前端 未结 4 467
梦毁少年i
梦毁少年i 2021-01-20 00:46

I know all of the philosophical arguments against preprocessors and macros in Java. I don\'t agree that just because some may abuse a language feature, it should be excluded

相关标签:
4条回答
  • 2021-01-20 01:16

    Logging should be a cross-cutting concern, anyway. It's possible to do what you want with aspects.

    0 讨论(0)
  • 2021-01-20 01:25

    Update @ralph Well, this is a question from 2+ years ago, but since I'm having the same need for __LINE__ and __FILE__ and you had mentioned SCALA; here are some ideas I'm having, using Scala macros (as of v2.10.0-RC1)

    def $currentPosition:String = macro _currentPosition;
    def _currentPosition(c:Context):c.Expr[String]={ import c.universe._;
      val pos = c.enclosingPosition;
      c.Expr(Literal(Constant(
        s"${pos.source.path}: line ${pos.line}, column ${pos.column}" )))
    }
    

    Macros being evaluated at compile-time, $currentPosition is replaced with a literal string that describes its position in the source code. For example, put in a println at line 13, it displays:

    /sandbox/tmp_juno_workspace2/LogMacro_Test/src/test/Trial.scala: line 13, column 15
    

    I have not played with these mechanisms extensively, but by tweaking the thing, one can develop the logging features (s)he requires (I should add that writing macros can be difficult - it is for me!).

    0 讨论(0)
  • 2021-01-20 01:27

    IMHO the "correct" way to achieve this would be to write a compiler plugin to perform the substitution, but is it really worth that amount of effort?

    0 讨论(0)
  • 2021-01-20 01:28

    You can use the compiler API to do this, but be careful. The "rules" for annotation processors/compiler plugins state that they are not supposed to modify the class being generated. Sun/Oracle may enforce this at anytime.

    For now, have a peek at http://projectlombok.org. It uses the compiler API to generate getters, setters and so forth. They have source code that you could use as a model, or you could contribute handlers to them.

    you could probably do something like the following:

    public class Foo {
      @FileName private static String fileName;
      @LineNumber private static int lineNumber;
      ...
      public void foo() {
         log(fileName, lineNumber, "some message");
      }
    }
    

    Then have the annotation processor change the fileName and lineNumber references to the actual file/line.

    Just be aware that this could break with later JDK versions. I don't know if Sun/Oracle will actually enforce the "don't modify the class being generated" rule, but they could.

    0 讨论(0)
提交回复
热议问题