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

change rangePos() in Globals to always return a range position #2110

Closed
scabug opened this issue Jun 29, 2009 · 4 comments
Closed

change rangePos() in Globals to always return a range position #2110

scabug opened this issue Jun 29, 2009 · 4 comments
Assignees

Comments

@scabug
Copy link

scabug commented Jun 29, 2009

Hi all,

I have a plugin which requires range positions for tree elements, so I can locate corresponding source. While it would suffice to have a plugin-specific option (e.g. detect if a plugin requires range positions to be maintained), I'm not convinced that the code complexity is worth it (also, if accepted, the interpreter's Global could be simplified to not override this). Stripping off the start and end data from each position object seems to be a premature optimization.

I did some benchmarks of compiling scala, and it doesn't seem to make much of a difference. For the first four, I ran `ant` after `ant clean`; the last was one run of `ant strap.lib` (sorry there aren't that many runs, the entire thing takes quite a bit of time).

rangepos: 8:34, 8:23, 8:27, 8:25; strap.lib 2:15
offset position: 8:18, 8:22, 8:32, 8:29; strap.lib 2:13

Also, if anyone wants another plugin example for documentation, I could try to get authorization to post that on a public URL (mine adds a unique identifier constant to a few function calls, and emits an XML file with source locations).

regards,
Nicholas

@scabug
Copy link
Author

scabug commented Jun 29, 2009

Imported From: https://issues.scala-lang.org/browse/SI-2110?orig=1
Reporter: gatoatigrado
Attachments:

  • rangepos.diff (created on Jun 29, 2009 10:51:23 PM UTC, 1215 bytes)

@scabug
Copy link
Author

scabug commented Jun 29, 2009

gatoatigrado said:
proposed patch

@scabug
Copy link
Author

scabug commented Jul 11, 2009

gatoatigrado said:
I see some changes related to this were checked in (RangePositions.scala)... if this becomes accessible for plugins at some point, please update the bug. Thanks!

@scabug
Copy link
Author

scabug commented May 12, 2012

@retronym said (edited on May 12, 2012 9:17:36 AM UTC):
Yep, this is available now under -Yrangepos.

Demonstrated using macros:

  ~/code/scratch/20120512 cat t2110.scala 
import language.experimental._

object Pos {
  def impl(c: reflect.makro.Context): c.Expr[String] = c.literal(c.enclosingPosition.toString)

  def pos = macro impl
}

  ~/code/scratch/20120512 cat t2110-client.scala 
object Test extends App {
  println(Pos.pos)
}

  ~/code/scratch/20120512 scalac210 -d macro.jar t2110.scala 

  ~/code/scratch/20120512 scalac210 -Yrangepos -classpath macro.jar -d client.jar t2110-client.scala 

  ~/code/scratch/20120512 scala210 -classpath macro.jar:client.jar 
TestRangePosition(/Users/jason/code/scratch/20120512/t2110-client.scala, 35, 39, 42)

@scabug scabug closed this as completed May 12, 2012
dkhalansky added a commit to dkhalansky/paradise-ng that referenced this issue Mar 14, 2018
A new compiler flag is required,
    -Yrangepos

Apparently, the best documentation on the flag is the Github
issue in which it was introduced:
scala/bug#2110

Each subtree in a compilation unit knows about its position in the
source file. The problem is, only the starting position is
specified, and there are no means to determine where the part of
sources corresponding to this subtree ends. That's where
`-Yrangepos` appears: it overrides the compiler behaviour to
propagate the end coordinates too.

The flag should be used with caution since it causes instability
https://github.com/scala/bug/issues?q=is%3Aissue%20rangepos%20is%3Aopen
and can disappear at any time, which is indicated by the `-Y`
prefix as opposed to `-X`.

An alternative solution was found here:
https://github.com/ghik/silencer/blob/690719727ee4974bd3a5e3f570be79a40133d3c8/silencer-plugin/src/main/scala/com/github/ghik/silencer/SilencerPlugin.scala#L55-L68
Here they traverse the tree and consider the last known position of
any of the subtrees to be the ending of the initial tree. This
approach works for modules, because it just so happens that a tree
for an invisible function `init()` is created just at the closing
curly bracket. However, the solution fails for methods:

     def hello() = println("Hello, world")
    /\                    /\
    |                     |
    start                 end

There is no subtree generated just after the end of the method's
body, so the last available position is the start of the last
lexeme.

If `-Yrangepos` proves too unreliable, it will be necessary to
adapt the second approach, for example, by finding the closing
pairs of all the opened brackets in the method. Annotations in
other contexts -- in types, in function arguments etc -- also
weren't tested, so maybe there will be problems there too. For now
we'll stick to `-Yrangepos`, so hopefully we won't have to deal
with the ad-hoc method.
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

2 participants