Showing posts with label eclipse. Show all posts
Showing posts with label eclipse. Show all posts

Monday, October 01, 2012

Current Development and Future Plans for Xtext and Xtend

It has been a couple of weeks now since we released Xtext and Xtend with Eclipse Juno. Time for an update on what we are doing and where we want to go. In the following I describe the main new topics the team is working on. In addition to what is described below there is of course also a lot of maintenance work we are doing, i.e. fixing bugs and improving the core framework. Also we are doing some awesome work for customers, which I’m not allowed to talk about (But, yes, you can hire us. Even the whole team!).

Editors For Other Platforms

We are experimenting with support for other IDE-platforms than Eclipse. The first platform we are looking at right now is the web, more concrete Orion. Other platforms we want to look at are Netbeans, Xcode, Visual Studio and IntelliJ. Also basic configuration settings for TextMate and the like could be something we will be looking at.
Which one do you think is most interesting?
This part of our work is funded by Zukunftsprogramm Wirtschaft


Improved Type System

The type system and linking for Xbase-based languages (Xtend falls into this class) is currently redeveloped. Although the existing one does a decent job it has some architectural flaws which makes it too slow when working with bigger files. The new one is fast and it can do even more and cooler things. Type inference, for instance, now uses control flow analysis. That is you can write the following:
val myMap = newHashMap
myMap.put(23, new StringBuilder)
myMap.put(42, "some string")
// myMap is of type Map<Integer, CharSequence> by now
There are some other new features, which are possible with the new typesystem and even more importantly it will fix the outstanding typing bugs and be a solid foundation for future improvements. I'm sure there will be a blog post about the details in the next couple of weeks.

Formatting

Xtend gets a new formatter. I’m already using it on a daily basis and must say that it works very well. Especially with a language like Xtend which is syntactically much more flexible than Java, you need to look into language idioms to make sure a formatter does what you expect. There will also be a preference page to adjust formatting settings, but it won’t have as many options as the Java formatter in the beginning. Would be nice to have some more beta testers and feedback. What kind of options do you want to see?
Although we are implementing the formatting for Xtend now, we plan to have a new or at least an improved API for all Xtext languages. And of course the formatting for the expression goes into Xbase.

Active Annotations

Active Annotations allow you to participate in the translation step from Xtend to Java source code. It’s a bit like Java’s annotation processing but much more flexible and less complicated to integrate at the same time. You basically declare an annotation and implement a processing method, where you define how to translate annotated Xtend code to Java. I'll write a separate blog post on this.
Also Sebastian is giving a sneak-preview on Active Annotations tomorrow at JavaOne and the feature will play an important role in the session Web Development with GWT and Xtend Olli and I are giving at EclipseCon in a couple of weeks.

Release Plans

Currently the overhauled type system has highest priority and we are targeting a release as soon as it is done. We hope to have it in December this year. That release will contain the formatting and might have an @Beta-flagged prototype for Active Annotations included. We plan to have a prototype for Xtext & Orion later this year as well, maybe the team can even give a so demo during their EclipseCon talk.

Additional Topics

I want to make contributing simpler. The idea is to provide a one click download, which materialises a working IDE, workspace and target platform on your box. The git repository should already be connected with our gerrit instance. Also we want to start writing breaking and ignored unit tests for defects so potential contributors can easily reproduce a problem and see how our test framework works. Let's see if we can make contributing and fixing bugs simple and fun.
Another topic is to provide an alternative for debugging Xbase-languages. Currently they work through JSR-045 which is great as long as you run your code in a standard JVM. Unfortunately JSR-045 isn't supported by Android's Dalvik-VM or GWT's new SuperDevMode. We need to come up with a solution for this as well.
Finally I want to mention that there is now a package for "Java and DSL Developers" on the Eclipse download page. It doesn't have a neat welcome page so far but it's a one-stop-shopping for people who want to get started with Xtend or Xtext (or both).

Monday, June 18, 2012

Vert.x and Xtend

Vert.x is a framework for asynchonous, scalable, concurrent applications. It’s conceptually very similar to node.js but runs on the JVM leveraging its native support for multiple threads.

Its programming model is based on a tell don't ask paradigm, that is you never wait for responses (and thereby block the current thread), but tell what to do as soon as a response is available by passing a handler. It also isolates state (even static one) so no locking is required.

Vert.x comes with special APIs for Java, JavaScript, Ruby and Groovy. They also plan to support Scala and Python.

So what about Eclipse's Xtend?


Xtend is not just another JVM language but an alternative way to write Java applications. It translates to comprehensible Java source code and unlike other JVM languages Xtend is 100% interoperable with Java and is designed to work great with existing Java APIs. That’s why no special API for Xtend is required.

The language is statically typed and features very advanced IDE support which tightly integrates with Java projects. A release of Xtend with lots of cool new features (e.g. debugging support) is just a couple of days away (June 27).

Some Examples


I have converted the Java examples shipped with vert.x to Xtend. The code is on github and is a fully working Eclipse project including working launch configurations to run and debug all the examples. If you are used to working in Eclipse, this is an easy way to try Vert.x : Just clone & import (using the "Import existing Projects into workspace" wizard) and you are done (Thanks to Doug for explaining the setup).

In the following I want to compare a couple of Java code snippets with their equivalent Xtend code, to demonstrate the expressiveness.

Https Example


The https example consists of two classes one for the client and one for the server. The client simple executed a get request on port 4443 and the server 'localhost' and prints the received data to System.out. Here's the Java code:
// Java
@Override
public void start() {
  vertx.createHttpClient()
    .setSSL(true)
    .setTrustAll(true)
    .setPort(4443)
    .setHost("localhost")
    .getNow("/", new Handler<HttpClientResponse>() {
      public void handle(HttpClientResponse response) {
        response.dataHandler(new Handler<Buffer>() {
          public void handle(Buffer data) {
            System.out.println(data);
          }
        });
      }
    });
  }
The Java API allows to configure the HttpClient using chained calls to setter methods. The last call is the get-request (getNow) where the path as well as a response handler is provided. Instead of blocking the current thread and waiting for the response you just tell what to do when the response is available. The Java API expects an instance of Handler<HttpClientResponse> for that.

Xtend allows to use the very same API with the following code:
// Xtend
override start() {
  vertx.createHttpClient => [
    SSL = true
    trustAll = true
    port = 4443
    host = "localhost"
    getNow("/") [
      dataHandler [ data |
        println( data )
      ]
    ]
  ]
}
First an http client is created, instead of using the chained setters (we could), we use the with-operator (=>) which allows us to use and initialize the http client from the left hand side within a lambda expression (the block in squared brackets). Within the lambda the HttpClient is bound to the implicit variable 'it', which like the self reference 'this' can be omitted when used as a receiver.
Next we call the setters using assignments, that is the expression
    SSL = true
is translated and equivalent to
    it.setSSL(true)
The interesting part is how we pass the response handler in Xtend :
    getNow("/") [
      dataHandler [ data |
        println( data )
      ]
    ]
The call to getNow(String, Handler<HttpClientResponse>) is done by passing just the string in the parentheses and a lambda expression right after the call. You need to understand two things here:
  1. If the last argument of a feature call is a lambda expression it can be passed after the method call.
  2. A lambda expression automatically coerces to the expected target type if it's an interface with just one method (which is a common idiom not only in vert.x).
Within the response handling a data handler is registered by calling setDataHandler(Handler<Buffer>) on the response object. Note that since this method gets just one lambda expression passed you don't have to write the parenthesis (in Xtend empty parenthesis are optional). Also note, that this time we gave the parameter a name (data) since I found it sightly more readable than :
    getNow("/") [
      dataHandler [
        println( it )
      ]
    ]
The Java implementation of the server prints out the header keys to the console and returns a tiny document:
// JAVA
public void start() {
  vertx.createHttpServer()
    .setSSL(true)
    .setKeyStorePath("server-keystore.jks")
    .setKeyStorePassword("wibble")
    .requestHandler(new Handler<HttpServerRequest>() {
      public void handle(HttpServerRequest req) {
        System.out.println("Got request: " + req.uri);
        System.out.println("Headers are: ");
        for (String key : req.headers().keySet()) {
          System.out.println(key + ":" + req.headers().get(key));
        }
        req.response.headers().put("Content-Type", "text/html; charset=UTF-8");
        req.response.setChunked(true);
        req.response.write("<html><body><h1>Hello from vert.x!</h1></body></html>", "UTF-8").end();
      }
    }).listen(4443);
  }
Translated to Xtend and applying the same patterns we used for the client this looks like the following:
// Xtend
override start() {
  vertx.createHttpServer => [
    SSL = true
    keyStorePath = "server-keystore.jks"
    keyStorePassword = "wibble"
    requestHandler [
      println("Got request: " + uri)
      println("Headers are: ")
      for (it : headers.entrySet) {
        println(key + ":" + value)
      }
      response.headers.put("Content-Type", "text/html; charset=UTF-8")
      response.chunked = true
      response.write('''
        <html>
          <body>
            <h1>Hello from vert.x!</h1>
          </body>
        </html>
        ''', "UTF-8").end
      ]
    listen(4443) 
  ]
}
There are two things worth mentioning in addition to what we've discussed in the first example:
  • You can use the variable name it every where. For instance in a for loop like in the code snippet above.
  • Xtend supports multiline string literals. The common literals using single quote or double quote can be multiline as well, but by using triple single quotes you get smart whitespace handling. That is the indentation before the tag will be pruned for all lines, i.e. the result will be well formatted. Also the triple quotes allow for having interpolation expressions, which are not used in this example.

Can we do even more?


Although the standard Java API already works very well there's room for special Xtend API. Vert.x for instance communicates with JSON objects a lot, which you might want to declare easily. Xtend doesn't support native JSON syntax, but you can design powerful APIs using a combination of extension methods and operator overloading. I added just three methods to be able to construct instances of vert.x's JsonObjects like this:
class JsonExample extends Verticle {
  
  override start() {
    val eb = vertx.eventBus
    val pa = 'vertx.mongopersistor'
    val albums = _(
      _(
        'artist'- 'The Wurzels',
        'genre'- 'Scrumpy and Western',
        'title'- 'I Am A Cider Drinker',
        'price'- 0.99,
        'categories'- _('action', 'comedy')
      ),
      _(
        'artist'- 'Vanilla Ice',
        'genre'- 'Hip Hop',
        'title'- 'Ice Ice Baby',
        'price'- 0.01
      ),
      _(
        'artist'- 'Ena Baga',
        'genre'- 'Easy Listening',
        'title'- 'The Happy Hammond',
        'price'- 0.50
      ),
      _(
        'artist'- 'The Tweets',
        'genre'- 'Bird related songs',
        'title'- 'The Birdy Song',
        'price'- 1.20
      )
    )
    
    // First delete everything
    eb.send(pa, _('action'- 'delete', 'collection'- 'albums', 'matcher'- _()))
    eb.send(pa, _('action'- 'delete', 'collection'- 'users', 'matcher'- _()))
    
    // Insert albums - in real life price would probably be 
    // stored in a different collection, but, hey, this is a demo.
    
    for (album : albums) {
      eb.send(pa, _(
        'action'- 'save',
        'collection'- 'albums',
        'document'- album
      ))
    }
    
    // And a user
    eb.send(pa, _(
      'action'- 'save',
      'collection'- 'users',
      'document'- _(
        'firstname'- 'Tim',
        'lastname'- 'Fox',
        'email'- 'tim@localhost.com',
        'username'- 'tim',
        'password'- 'password'
      )
    ))
  }  
}
These are the three extension methods:
  def static <T> Pair<String,T> operator_minus(String key, T value) {
    new Pair(key, value)
  }
  
  def static JsonArray _(Object ... entries) {
    val result = new JsonArray
    for (e : entries) {
      switch e {
        String : result.addString(e)
        Number : result.addNumber(e)
        Boolean : result.addBoolean(e)
        JsonObject : result.addObject(e)
        JsonArray : result.addArray(e)
      }
    }
    return result
  }
  
  def static JsonObject _(Pair<String, ?> ... entries) {
    val result = new JsonObject
    for (e : entries) {
      switch value : e.value {
        String : result.putString(e.key, value)
        Number : result.putNumber(e.key, value)
        Boolean : result.putBoolean(e.key, value)
        JsonObject : result.putObject(e.key, value)
        JsonArray : result.putArray(e.key, value)
      }
    }
    return result
  }

Sunday, June 10, 2012

Xtend - The Movies Example

The upcoming release of the new version of Xtend is just a couple of days away (June 27). Although the technical (OSGi) version is 2.3, for me it's really more like a 1.0 release. It now has everything you need to write beautiful Java programs, like the little movies example we have been using in some workshops we did recently.

The movies example is also included in the example project that will be shipped with the Eclipse plug-in and is about reading a file of movie data in and doing some queries on it.

The Data

The movie database is a plain text file (data.csv) with data sets describing movies. Here's an example data set:

Naked Lunch  1991  6.9  16578  Biography  Comedy  Drama  Fantasy

The values are separated by two spaces. The columns are :

  • title
  • year
  • rating
  • numberOfVotes
  • categories (where any number of categories is allowed)

Let's start by declaring a data type Movie reflecting the data set:

@Data class Movie {
  String title
  int year
  double rating
  long numberOfVotes
  Set categories 
}

The @Data annotation will turn this class into a value object, that is the compiler will create

  • a getter-method for each field,
  • a hashCode()/equals() implementation,
  • implementation of Object.toString() and
  • a constructor accepting values for all fields in the declared order.

Parsing The Data

Let's now define another class which reads the text file into a list of movies so that we can do some analysis on the data. We will access the data from within a JUnit test, so simply initializing a field is appropriate:

import java.io.FileReader
import java.util.Set
import static extension com.google.common.io.CharStreams.*

class Movies {

  val movies = new FileReader('data.csv').readLines.map[ line |
    val segments = line.split('  ').iterator
    return new Movie(
      segments.next, 
      Integer::parseInt(segments.next), 
      Double::parseDouble(segments.next), 
      Long::parseLong(segments.next), 
      segments.toSet
    )
  ]
}

The field's type (List) is inferred from the expression on the right hand-side and we want the field to be final, so we declare it as a value using the keyword code val.

The initialization on the right hand side first creates a fresh instance of java.io.FileReader. Then the method readLines() is invoked on it. But if you have a look at FileReader you won't find such a method. It's in fact a static method coming from Google Guava's CharStream and is imported as an extension :

import static extension com.google.common.io.CharStreams.*

CharStream.readLines(Reader) returns a List on which we call another extension method called map. That one is defined in Xtend's runtime and is always imported and therefore automatically available on all lists. The map-method expects a function as the parameter. It invokes that function for each value in the list and returns a list containing the results of the function invocations.

Function objects are created using lambda expression (the code in squared brackets). Within the lambda we process a single line from the text file and turn it into a movie by splitting the string using the separator and calling iterator() on the result. As you might know java.lang.String.split(String) returns a string array (String[]). But as Xtend auto-converts arrays to lists when needed, we can call iterator() on it.

val segments = line.split('  ').iterator

Now we use the iterator to create an instance of Movie:

return new Movie (
  segments.next, 
  Integer::parseInt(segments.next), 
  Double::parseDouble(segments.next), 
  Long::parseLong(segments.next), 
  segments.toSet
)

Answering Some Questions

Now that we've the text file turned into a List, we are ready to do some queries on it. We use JUnit to make the individual expressions executable.

Question 1: How Many Action Movies Are Contained?:

@Test def void numberOfActionMovies() {
  assertEquals(828, 
    movies.filter[categories.contains('Action')].size)
}

It's using the extension method filter to filter the movies. The lambda expression checks whether the current movie's categories contains the entry 'Action'. Note that unlike the lambda we used to turn the lines in the file into movies, we haven't declared a parameter name this time. We could have given the parameter an explicit name 'movie' by writing the following:

assertEquals(828, movies.filter[movie | movie.categories.contains('Action')].size)

But if we leave out the name and the vertical bar the variable is automatically named 'it' which (like this) is an implicit variable. That's why we can either write

assertEquals(828, movies.filter[it.categories.contains('Action')].size)

or just

assertEquals(828, movies.filter[categories.contains('Action')].size)

Lastly we call size on the resulting iterable, which again is an extension method (java.lang.Iterable doesn't define such a method).

Question 2: What's The Year The Best Movie From The 80ies Was Released.

@Test def void yearOfBestMovieFrom80ies() {
  assertEquals(1989, 
    movies.filter[(1980..1989).contains(year)].sortBy[rating].last.year)
}

Here we filter out all movies where the year is not included in the range from 1980 to 1989 (the 80ies). The range-operator (..) again is an extension defined for two ints and returns an instance of org.eclipse.xtext.xbase.lib.IntegerRange.

The resulting iterable then is sorted by the rating of the movies. Since it's sorted in ascending order, we take the last movie from the list and return its year.

We could have sorted descending and take the head of the list as well (note the minus sign):

movies.filter[(1980..1989).contains(year)].sortBy[-rating].head.year

Btw. the calls to movie.year as well as movie.categories in the previous example of course access the corresponding getter methods, which were generated because of the @Data annotation.

Question 3: The Sum Of All Votes Of The Top Two Movies

@Test def void sumOfVotesOfTop2() {
  assertEquals(47_229, 
    movies.sortBy[-rating].take(2).map[numberOfVotes].reduce[a, b| a + b])
}

First the movies are sorted by rating, then we take the best two. Next the list of movies is turned into a list of their numberOfVotes using the map function. Now we have a List which can be reduced to a single Integer by adding the values.

Monday, May 07, 2012

Martin Fowler's State Machine DSL with Xtext 2.3


In his book on domain-specific languages, Martin Fowler introduces a small example along which he shows different techniques to implement a domain-specific language. The example goes like this:

Imagine you work for a company specialized on developing and installing systems for secret compartments and you have many customers with very different mechanisms. Mrs. H for instance wants to have a secret panel in her bedroom, which can only be opened after the door has been closed, the second drawer in her chest has been opened and the bedside light was turned on. Also the panel should be closed and locked immediately after someone opens the door - no matter in what state the system is in that case.

Martin proposes the following script as an appropriate definition of Mrs. H's secret compartment system:

events
  doorClosed
  drawOpened
  lightOn   
  reset doorOpened
  panelClosed
end

commands
  unlockPanel
  lockPanel
  lockDoor
  unlockDoor
end

state idle
  actions {unlockDoor lockPanel}
  doorClosed => active
end

state active
  drawOpened => waitingForLight
  lightOn    => waitingForDraw
end

state waitingForLight
  lightOn => unlockedPanel
end

state waitingForDraw
  drawOpened => unlockedPanel
end

state unlockedPanel
  actions {unlockPanel lockDoor}
  panelClosed => idle
end

The script starts with two sections which declare the events and the commands. After that the different states are declared. Some of them execute declared commands as a side effect (the actions block). Also they contain declarations of transitions, i.e. to what state the system switches when a certain event is fired.

As I have already implemented this language with previous versions of Xtext, I'd like to make it a bit more interesting this time. Let's replace the more or less useless declaration of commands with the possibility to write and call real code!

events
  doorClosed
  drawOpened
  lightOn   
  reset doorOpened
  panelClosed
end

state idle
  do { 
    println("opened the door.")
    println("locked the panel.")
  }
  doorClosed => active
end

state active
  drawOpened => waitingForLight
  lightOn    => waitingForDraw
end

state waitingForLight
  lightOn => unlockedPanel
end

state waitingForDraw
  drawOpened => unlockedPanel
end

state unlockedPanel
  do { 
    println("opened the panel.")
    println("locked the door.")
  }
  panelClosed => idle
end

As you can see the main change is that you are now able to call Java libraries right from within your state machine. I want these expressions to be statically typed (incl. full support for Java generics) and to keep the code as readable and dense as the rest of the DSL we need to have type inference like in Scala. Feature-wise everything should be supported, from for-loops to conditional logic, from the typical literals to more advanced concepts like lambda expressions (it's 2012 after all). 

But how would we talk to a door resp. panel service in order to open and close them? We could use static methods, but that's bad design since then the application is hardly testable and you cannot easily switch the concrete implementations behind these services. So let's use dependency injection. 
To support that I added a services block to the language where you list all required services. Now we can use these services within the action code :

events
  doorClosed
  drawOpened
  lightOn   
  reset doorOpened
  panelClosed
end

services
  DoorService door
  PanelService panel
end

state idle
  do { 
    door.open
    panel.close
  }
  doorClosed => active
end

state active
  drawOpened => waitingForLight
  lightOn    => waitingForDraw
end

state waitingForLight
  lightOn => unlockedPanel
end

state waitingForDraw
  drawOpened => unlockedPanel
end

state unlockedPanel
  do { 
    door.close
    panel.open
  }
  panelClosed => idle
end

Our language would now be very testable and should integrate nicely with any Java project. 

How Do I Implement Such A Language In Xtext?

To get a full implementation of this DSL, including not only a parser, linker, unparser, etc. but also a compiler generating readable and executable Java code as well as having nice integration in Eclipse, you need to create a fresh Xtext project, using the wizard and define the following grammar:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Statemachine :
  {Statemachine}
  ('events' 
    events+=Event+ 
  'end')?
  ('services'
    services+=Service*
  'end')?
  states+=State*;

Service :
  type=JvmTypeReference name=ID;

Event:
  resetEvent?='reset'name=ID;

State:
  'state' name=ID
    ('do' action=XBlockExpression)?
    transitions+=Transition*
  'end';

Transition:
  event=[Event] '=>' state=[State];

I don't want to go into a detailed explanation of the grammar language, since that is explained in the documentation. But note, that in order to be able to write full Java types in the service declaration we refer to a library grammar rule (JvmTypeReference). The same applies for the expressions: The library grammar 'org.eclipse.xtext.xbase.Xbase' predefines the full expressions and all we have to do here is to import the grammar in the first line and call the rule XBlockExpression within the rule State.

Now that we have defined the syntax of our language, we need to tell how it is translated to Java. For that matter we write some code, which creates a Java DOM out of the state machine DOM produced by the parser. To make this very readable and concise Xtext comes with an internal DSL implemented in the programming language Xtend. The actual code looks like this:

 def dispatch void infer(Statemachine stm, 
                         IJvmDeclaredTypeAcceptor acceptor, 
                         boolean isPreIndexingPhase) {
   
   // create exactly one Java class per state machine
   acceptor.accept(stm.toClass(stm.className)).initializeLater [
     
     // add a field for each service annotated with @Inject
     members += stm.services.map[service|
       service.toField(service.name, service.type) [
         annotations += service.toAnnotation(typeof(Inject))
       ]
     ]
     
     // generate a method for each state having an action block
     members += stm.states.filter[action!=null].map[state|
       state.toMethod('do'+state.name.toFirstUpper, state.newTypeRef(Void::TYPE)) [
         visibility = PROTECTED
         
         // Associate the expression with the body of this method.
         body = state.action
       ]
     ]
     
     // generate a method containing the actual state machine code
     members += stm.toMethod("run"newTypeRef(Void::TYPE)) [
       
       // the run method has one parameter : an event source of type Provider 
       val eventProvider = stm.newTypeRef(typeof(Provider), stm.newTypeRef(typeof(String)))
       parameters += stm.toParameter("eventSource", eventProvider)
       
       // generate the body
       body = [append('''
         boolean executeActions = true;
         String currentState = "«stm.states.head.name»";
         String lastEvent = null;
         while (true) {
           «FOR state : stm.states»
             if (currentState.equals("«state.name»")) {
               «IF state.action != null»
                 if (executeActions) {
                   do«state.name.toFirstUpper»();
                   executeActions = false;
                 }
               «ENDIF»
               System.out.println("Your are now in state '«state.name»'. Waiting for [«
                 state.transitions.map[event.name].join(', '].");
               lastEvent = eventSource.get();
               «FOR t : state.transitions»
                 if ("«t.event.name»".equals(lastEvent)) {
                   currentState = "«t.state.name»";
                   executeActions = true;
                 }
               «ENDFOR»
             }
           «ENDFOR»
           «FOR resetEvent : stm.events.filter[resetEvent]»
             if ("«resetEvent.name»".equals(lastEvent)) {
               System.out.println("Resetting state machine.");
               currentState = "«stm.states.head.name»";
               executeActions = true;
             }
           «ENDFOR»
           
         }
       ''')]
     ]
   ]
 }


That's all you need. With just the grammar and the Xtend code above you have implemented the full language! I've pushed the full project to github.
This is what the Java code generated for Mrs. H's controller looks like.

What Do You Get?

As already mentioned the expressions are feature complete and statically typed. The compiler can be run from any Java process (e.g. ant, maven, gradle, command line). Also the tooling is just like you would expect: content assist, coloring, hovers, refactorings, dead code analysis and even debugging work out of the box:


Content Assist For Expressions

Call-Hierarchy Integrated in JDT
Content Assist For Types

Dead Code Analysis






Friday, April 27, 2012

Xtend - New Language Features coming in M7

The team has been busy adding useful new features to Xtend (and all other languages built on top of Xtext's JVM-support). The upcoming M7 build (May 9) will come with the following enhancements:

"With"-Operator

A new operator '=>' has been added to the language and a corresponding extension method for java.lang.Object on the left hand side and a lambda expression on the right hand side. 
The with operator allows you to write:

new JTextField => [
  text = 'My Text'
]

Think of it as a let-expression, which allows for binding any object to the scope of the block, in order to do side-effects in it. Very handy when initializing objects.

Properties

A new annotation @Property will generate a Java-Bean-style getter and setter (if the field is not final) for an annotated field.

class Person {
  @Property String firstName
  @Property String lastName
}

The field itself will be renamed to _fieldname, to make one accesses the getter (resp. setter) when using the property syntax. OF course a getter or setter is only generated when not explicitly defined.

Data Classes (Value Objects)

Another annotation @Data, will turn an annotated class into a value object class. A class annotated with @Data has the following effect:
  1. all fields are flagged final, 
  2. getter methods will be generated (if not existent), 
  3. a constructor will be generated (if not existent),
  4. equals(Object) / hashCode() methods will be generated (if not existent),
  5. a toString() method will be generated (if not existent). 
Example:

@Data class Person {

  String firstName
  String lastName
}

For now the processing of the two annotations is hard coded into the compiler. However as described in this bugzilla, we want to add support for library level annotation processing. This will allow for adding other annotations like @Delegate etc. Also we want to make this very easy so you can easily define your own project-specific annotations. Unfortunately this will not make it into the upcoming release.

Multiple Classes in One File

You can now have any number of classes in a single file. Also the name of the first class must no longer match the file's name. But still if it matches it will be renamed in a rename refactoring.

Enhanced Field Declarations

Type inference for fields is now working, also the val and var keywords are available. 
Example:

class Person {
  @Property val firstName = 'Hans'
  @Property var lastName = 'Meier'
} 

Other areas we've been working on

Besides enhancing the language, we put a lot of effort into the IDE as well. Several new features like for instance a quick assist to add method declarations have been added. Also Sebastian is working on a rewrite of the type inference and linking engine, since the current implementation turned out to be a bit slow in certain situations.

Tuesday, March 20, 2012

Xtend 2.3 beta version available

Today we announce the availability of the first beta version for the planned release in June. As you might know Xtend is a statically typed, functional and object-oriented programming language targeting the Java Virtual Machine. As opposed to other Java alternatives Xtend compiles to readable Java source code, provides state-of-the-art Eclipse integration and is 100% compatible with existing Java libraries and frameworks.
Besides many bug fixes, performance improvements and some minor language enhancements (number literals, varargs, etc.), the big leap has been done on the tooling side. 
Debugging through Xtend and Java sources now works transparently side by side. As Xtend generates Java source code, the user can even switch between the generated Java source and the original Xtend source while in a debugging session. This equivalence of languages is also stressed by a special Eclipse view that allows to inspect which parts of the generated Java code are derived from which segments of Xtend code.

The new Eclipse plug-in for Xtend now integrates seamlessly with Eclipse’s Java Development Tools. No matter whether you click on a stack frame in a printed exception, on a failing unit tests, or on some search result in the call hierarchy, find references or the type hierarchy view: If the target element has been implemented in Xtend, the Xtend editor will open up and select the correct source location. 
In case you want to see the generated Java source code, there’s the new ‘Generated Code’ view. It shows the generated code and marks the correct ranges corresponding the current selection in the Xtend editor. With that you can understand how Xtend is translated to Java in detail. Looking at the generated Java will help you getting familiar with the language.

See the "New & Noteworthy" page for more details and more cool new features.
The final release is planned for June 27 as part of Eclipse Juno, this year’s Eclipse release train. Till then we want to focus on stabilizing, improving performance and making sure nothing gets into the way of a great user experience. We are extremely happy with the beta version, and enjoying working on it and in it on a daily basis. There’re still a lot of things to do and we hope to get a lot of feedback from the community, so we are able to address any outstanding issues till June.
The beta version is now available for through the following Eclipse p2 update site : http://download.eclipse.org/modeling/tmf/xtext/updates/composite/milestones/

Wednesday, January 04, 2012

Collection Literals in Java (or a hidden gem in Eclipse JDT)

Yesterday I watched a devoxx presentation by Joshua Bloch about the Evolution of Java" which I enojoyed.
In that talk he discusses the various language features which have been added to Java in terms of how important resp. problematic their addition was. I agree with most of his reasoning but not with the following two:

  • static imports
    He said they are ok, but not too useful and that he makes use of them only about once a month.
  • diamond operator
    He claimed, that this was an important addition, since now creating new collections is less noisy.

I disagree for the following reasons

Joshua Bloch actually also helped designing a very cool collection library which is part of Google Guava. If you don't know it, have a look! Besides other useful stuff that library contains factory methods for the common collection types.
For instance to create an ArrayList you could write the following:

List<String> names = Lists.newArrayList();

Making use of a static import one can write something like this:

import static com.google.common.collect.Lists.*;
...
List<String> stuff = newArrayList("Foo","Bar","Baz");

But the inconvenience of adding a static import every time you want to create a new collection is a problem. JDT to the rescue! There is an almost hidden gem in JDT, that allows you to have static import favorites for content assist. This is my configuration:



Having your static imports configured here, will make their methods available through code completion without having an import first. Instead the import will automatically be added as you apply the proposal.


I only create collections that way, because it's so easy and readable, and I don't have much use cases for the diamond operator (in fact inference on the left hand side would have been much more interesting). On the other hand I use static imports in almost any class file.

Btw, those static imports not only make the factory methods available but also all the nice higher-order functions like, collect, filter, etc..
A welcome productivity gain!

Friday, November 04, 2011

New Xtend Website

With the recent release of Xtext 2.1, also the language Xtend got improved in various ways.
Today we announce a new landing page for Xtend:


So go find out about this little Java-enhancer and if you happen to be at EclipseCon Europe today 
make sure to attend Sebastian's talk on Xtend.
   
    Theater Stage at 2 p.m.