On Fri, Feb 3, 2012 at 4:31 PM, Iulian Dragos
<iulian...@typesafe.com> wrote:
> i) I can't find a way to navigate up to the parent of the given Tree object,
> is there a way to do that? I could get the children by the .children but I
> am not sure about how to get the 'parent'.
>
>
> There's no link to the parent, the AST is a 'real' tree. What would you like
> to do, maybe there's an alternative way? I really think it would be good to
> ask these questions on scala-ide-dev on Google Groups, since more people
> might be interested by the answers (and the whole IDE team reads the list).
>
I joined scala-ide-dev and CC'd the list.
The problem we are trying to solve is allowing people to get good IDE
support for custom style traits in ScalaTest. ScalaTest lets users
customize the syntax of their tests to meet their needs. We'd like
folks who do that to be able to get IDE support as good as if they use
the built-in style traits. It is fundamental to the design of
ScalaTest that people can customize it in this way, and I don't want
them to have to give up good IDE support if they do.
The hard part is enabling a pop up menu that runs selected tests when
someone selects some arbitrary code and right clicks to get a pop up
context menu. How does the IDE know what the tests are, in a framework
where that can be customized? Whatever we do needs to be very fast,
because users want that pop up to feel like it happens just about
immediately.
The current approach we are trying is to annotate ScalaTest's built in
style traits with a Style annotation, and make that annotation
available for users. When a user opens a source file containing test
classes, the IDE can follow the linearization of each of those classes
until it bumps into the first one that has a Style annotation. This
can be done before the user right clicks if need be, right when the
file is opened, and after each time it compiles successfully, etc.
But it probably would be fast enough to do it when they right click as
well. So one thing we want to know is, is there an easy way to
traverse the linearization of a class?
Then, once the Style annotation is found, it can have a "Finder" class
specified in it. The IDE can instantiate this class (again this could
be done ahead of time, but would be fast enough on demand too), and
the Finder has a method that takes an AST (wrapped in ScalaTest AST
wrapper classes to unify the API across the different IDEs), and that
method returns a "Selection" that indicates what the tests are. The
Selection tells the IDE what to put on the context menu, and what to
pass to ScalaTest if the user selects that menu item.
We have done this in IntelliJ and it was plenty fast enough. But in
IntelliJ we were able to go to the parent of an AST node. So (I think)
we have it giving just the selected bit of the AST to the Finder, and
it traverses outward via the parent pointers sometimes to get more
context. What I think we'll likely need to do given the presentation
compiler's AST does not have parent pointers is give the whole class
AST and somehow highlight what the selected part is (or where in the
tree the use right clicked, if they clicked without otherwise
selecting anything. This would work both on ASTs with parent nodes
(IntelliJ) and those without (Eclipse and NetBeans.
Chee Seng is working on this so I may have some of the details wrong.
If so, Chee Seng please correct me.
Thanks.
Bill
----
Bill Venners
Artima, Inc.
http://www.artima.com
Hi Iulian,
On Fri, Feb 3, 2012 at 4:31 PM, Iulian Dragos
<iulian...@typesafe.com> wrote:
> i) I can't find a way to navigate up to the parent of the given Tree object,
> is there a way to do that? I could get the children by the .children but I
> am not sure about how to get the 'parent'.
>
>
> There's no link to the parent, the AST is a 'real' tree. What would you like
> to do, maybe there's an alternative way? I really think it would be good to
> ask these questions on scala-ide-dev on Google Groups, since more people
> might be interested by the answers (and the whole IDE team reads the list).
>
I joined scala-ide-dev and CC'd the list.
The problem we are trying to solve is allowing people to get good IDE
support for custom style traits in ScalaTest. ScalaTest lets users
customize the syntax of their tests to meet their needs. We'd like
folks who do that to be able to get IDE support as good as if they use
the built-in style traits. It is fundamental to the design of
ScalaTest that people can customize it in this way, and I don't want
them to have to give up good IDE support if they do.
The hard part is enabling a pop up menu that runs selected tests when
someone selects some arbitrary code and right clicks to get a pop up
context menu. How does the IDE know what the tests are, in a framework
where that can be customized? Whatever we do needs to be very fast,
because users want that pop up to feel like it happens just about
immediately.
The current approach we are trying is to annotate ScalaTest's built in
style traits with a Style annotation, and make that annotation
available for users. When a user opens a source file containing test
classes, the IDE can follow the linearization of each of those classes
until it bumps into the first one that has a Style annotation. This
can be done before the user right clicks if need be, right when the
file is opened, and after each time it compiles successfully, etc.
But it probably would be fast enough to do it when they right click as
well. So one thing we want to know is, is there an easy way to
traverse the linearization of a class?
Then, once the Style annotation is found, it can have a "Finder" class
specified in it. The IDE can instantiate this class (again this could
be done ahead of time, but would be fast enough on demand too),
and
the Finder has a method that takes an AST (wrapped in ScalaTest AST
wrapper classes to unify the API across the different IDEs), and that
method returns a "Selection" that indicates what the tests are. The
Selection tells the IDE what to put on the context menu, and what to
pass to ScalaTest if the user selects that menu item.
We have done this in IntelliJ and it was plenty fast enough. But in
IntelliJ we were able to go to the parent of an AST node. So (I think)
we have it giving just the selected bit of the AST to the Finder, and
it traverses outward via the parent pointers sometimes to get more
context. What I think we'll likely need to do given the presentation
compiler's AST does not have parent pointers is give the whole class
AST and somehow highlight what the selected part is (or where in the
tree the use right clicked, if they clicked without otherwise
selecting anything. This would work both on ASTs with parent nodes
(IntelliJ) and those without (Eclipse and NetBeans.
Hi all,
Hi Iulian,
I figure out about the dependent type, I have refactored out the code
to transform the AST and finding ScalaTest selected tests into the
following class:-
https://github.com/cheeseng/scala-ide/blob/master/org.scala-ide.sdt.core/src/scala/tools/eclipse/launching/ScalaTestFinder.scala
and let ScalaTestLaunchShortcut to pass in the
ScalaPresentationCompiler.
rawChildren match {case primary :: rest =>if (primary.isInstanceOf[MethodDefinition] && primary.name == "this")rest.toArray
Another problem I have is loading classes from the client's project
classpath, the reason we need to do this is because user could write
their own custom finder implementation and put the jar/class in their
project classpath, the code I am using currently to load the test base
class (consequently the finder) is using Class.forName (line 243 in
ScalaTestFinder.scala), which probably is not correct. May I know
what's the correct way to achieve that?
Hi iulian,
I have checked in the code to load classes from client project's
classpath, to create the ClassLoader I use the following codes:
val loaderUrls = scProject.classpath.map{ cp =>
val cpFile = new File(cp.toString)
if (cpFile.exists && cpFile.isDirectory && !
cp.toString.endsWith(File.separator))
new URL("file://" + cp + "/")
else
new URL("file://" + cp)
}
val loader:ClassLoader = new URLClassLoader(loaderUrls.toArray,
getClass.getClassLoader)
I then use reflection to call the Finder.find in ScalaTestFinder. I
tested it using a custom Finder implemented in the client project and
it seems to be working correctly.
Does the code looks right to you?
Great to hear about your progresses!
> The finder will be used to detect selected test/scope from ScalaTest
> suite source file, style traits in ScalaTest (load from scalatest.jar
> in client project's classpath) will be annotated with @Style like
> this:-
>
> @Style("org.scalatest.finders.FunSuiteFinder")
> trait FunSuite extends Suite {
> ...
> }
Why not @Style(classOf[FunSuiteFinder]) ? Just wonder...
-- Mirco
Hi Chee Seng,
Say, can you answer Mirco's question? Is the reason because the class
may not be on the class path? That's my guess, but please let Micro
(and me too) know the real reason.
Thanks.
Bill
--
Hi Micro and Bill,We were using @Style(classOf[FunSuiteFinder]) when finders stuff were in scalatest.jar, but after it moved into scalatest-finders.jar, we would need to add the scalatest-finders.jar dependency in scalatest in order to use @Style(classOf[FunSuiteFinder]), it may be still ok to do so, just try to de-couple them.
Another reason is that it makes reading the style class easier using 'static' way in the AST, I am not sure in the presentation compiler AST (currently using reflection), but I have bad experience in retrieving the annotation in 'static' way while doing in IntelliJ AST, as Alex explained that they didn't fully implemented that yet as they don't need them for now.
The style trait classes (FeatureSpec in the above example) comes from
a compiled jar file most of the time, and we need a way to get the
@Style annotation from it. The simplest way is via reflection (using
it currently in eclipse plugin), in intellij I was trying to get it
using 'static' way:- from the AST directly. I was trying to use
intellij PSI API to get the class name in the @Style, but without a
success (may be due to the class is loaded from a compiled jar file,
instead of source file - I am not sure). The best I got was a plain
text of:-
@Style("org.scalatest.finders.FeatureSpecFinder")
So I parse the plain text to extract the finder class name out, I am
thinking that using @Style(classOf[FeatureSpecFinder]) may be harder
to parse, but I could be wrong. As I am currently still using
reflection in eclipse plugin, do kindly enlighten me if there is a
better way to get the @Style info, perhaps using something from the
presentation compiler.
The reason for the creation of Finders is that we figured out that
selection in different style traits can be very different from one to
the other. Furthermore we allow custom style traits to be created and
we want to allow custom style traits to have a way to write its own
finder that IDE/tools can recognize and use it. The finder logic
depends on the style trait, so the creator of the style trait should
have the best knowledge to write the finder.
Sorry for the long email, just trying to explain where we are coming
from. I hope my explanation isn't too bad, do feel free to let us
know what you think about the approach. :)
We are going to work on the view that display the running result this
week, it should be similar to the JUnit plugin one in look and when
clicked, it should enable user to hop to correct line number in the
source file. After completing the view I think we can do a pull
request.
Best,
Ismael
I'll be back soon working on luc's review, hopefully we can move it to fully public soon.