Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent DocDef nodes visibility at macro expansion time #8904

Closed
scabug opened this issue Oct 13, 2014 · 3 comments
Closed

Inconsistent DocDef nodes visibility at macro expansion time #8904

scabug opened this issue Oct 13, 2014 · 3 comments
Assignees

Comments

@scabug
Copy link

scabug commented Oct 13, 2014

I'm contributing to the MacWire project which leverages scala macros to perform compile-time dependency injection.

Few days ago we encountered a problem - I'm not sure if my problem is a kind of compiler bug or some undocumented but intentional behaviour.

Consider following code snippet:
{code}package com.example

trait SomeTrait {

/**

  • some comment what this service does.
    */
    lazy val someService: Service = MyService

}{code}

While running 'sbt compile', above code produces the following syntax tree:
{code}ClassDef(
Modifiers(ABSTRACT | DEFAULTPARAM / TRAIT),
com.example.SomeTrait,
List(),
Template(
List(
Select(Ident(scala), TypeName("AnyRef"))
),
noSelfType,
List(
DefDef(Modifiers(), TermName("$init$"), List(), List(List()), TypeTree(), Block(List(), Literal(Constant(())))),
ValDef(Modifiers(LAZY), TermName("service "), Ident(com.example.Service), Ident(com.example.MyService))
)
)
){code}
and 'sbt doc' results in:
{code}ClassDef(
Modifiers(ABSTRACT | DEFAULTPARAM / TRAIT),
com.example.SomeTrait,
List(),
Template(
List(
Select(Ident(scala), TypeName("AnyRef"))
),
noSelfType,
List(
DefDef(Modifiers(), TermName("$init$"), List(), List(List()), TypeTree(), Block(List(), Literal(Constant(())))),
DocDef(
DocComment(
/**
* some comment what this service does.
*/,
RangePosition(..), NoPosition()
),
ValDef(Modifiers(LAZY), TermName("service "), Ident(com.example.Service), Ident(com.example.MyService))
)
)
)
){code}

The difference is in Template bodies - in the latter case ValDef is wrapped within DocDef node.

AFAIK DocDefs should be removed (flattened) by analizer, according to comment in source code https://github.com/scala/scala/blob/2.11.x/src/compiler/scala/tools/nsc/ast/Trees.scala#L24.

Even if presence of DocDefs at 'doc' task isn't a bug (I'm only guessing that macro expansion is done after scaladoc generation, in later compiler phase. Or maybe DocDefs are necessary here to generate doc?), then I think that inconsistency between ASTs may be an issue.

I found, that @retronym solved similar problem with constructors hidden by DocDef node: scala/scala@c4561c1

Unfortunately, we can't just match against DocDef in our code (https://github.com/adamw/macwire/blob/master/macros/src/main/scala/com/softwaremill/macwire/ValuesOfTypeInEnclosingClassFinder.scala#L16-L22) because it's not present in public Trees API.
Thus the only working workaround is to disable macro expansion at compile:doc.
(I have an idea to try match on DocDefs using quasiquotes, but I haven't tested it yet)

Source code for the MacWire is available here: https://github.com/adamw/macwire
Here's an issue report, caused by described DocDef presence: softwaremill/macwire#21
And simple project, which we used to reproduce the problem: https://github.com/mkubala/macwire-bug-demonstration

I think that DocDef should be always invisible at macro expansion time or visible, with appropriate DocDef extractor available in public API.
IMHO anything will be better than lack of consistency.

@scabug
Copy link
Author

scabug commented Oct 13, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8904?orig=1
Reporter: @mkubala
Affected Versions: 2.11.0, 2.11.1, 2.11.2

@scabug
Copy link
Author

scabug commented Oct 14, 2014

@xeno-by said:
This is indeed a problem, which we want to fix. Here's an open issue about that: #7993.

Unfortunately, short of disabling macro expansion at doctime, I don't think there's an easy workaround. The best I can imagine here at the moment is to cast to Global and use the internal APIs to see through DocDefs.

@SethTisue
Copy link
Member

duplicate of #7993 afaict, correct me if I'm wrong

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants