The Object Teams Blog

Adding team spirit to your objects.

Get for free what Coin doesn’t buy you

with 2 comments

Ralf Ebert recently blogged about how he extended Java to support a short-hand notation for throwing exceptions, like:

   throw "this is wrong";

It’s exactly the kind of enhancement you’d expect from Project Coin, but neither do they have it, nor would you want to wait until they release a solution.

At this point I gave it a few minutes, adapted Ralf’s code, applied Olivier’s suggestion wrapped it in a little plugin et voilà:

Install

Use this p2 repository, check two features…
Install Medal Java Extensions
…install and restart, and you’re ready to use your “Medal” IDE:
Medal IDE

So that’s basically the same as what Ralf already showed except:

It’s a module!

In contrast to Ralf’s patch of the JDT/Core my little plugin can be easily deployed and installed into any Eclipse (≥3.6.0). It just requires another small feature called “Object Teams Equinox Integration” or “OT/Equinox” for short.

So we’re all going to use our private own ”’dialects of Java?”’ Hm, firstly, once compiled this is of course plain Java, you wouldn’t be able to tell that the sources looked “funny”.

And: here’s the Boss Key: when somebody sniffs about your monitor, a single click will make Eclipse behave “normal”:
Boss Key
In other words, you can ”’dynamically enable/disable”’ this feature at runtime. The OT/Equinox Monitor view in the snapshot shows all known Team instances in the currently running IDE, and the little check boxes simply send activate() / deactivate() messages to the selected instance.

I coined the name Medal as our own playground for Java extensions of this kind. Feel free to suggest/contribute more!

Implementation

For a quick introduction on how to setup an OT/Equinox project in Eclipse I’d suggest our Quick Start (let me know if anything is unclear). For this particular case the key is in defining one little extension:
Extension
which the package explorer will render as:
Viewed in the Package Explorer
Drilling into the Team class ThrowString you’ll see:
ThrowString Outline
The Team class contains two Role classes:

  • Role DontReport binds to class ProblemReporter (not shown in the Outline), intercepts calls to ProblemReporter.cannotThrowType and if the type in question is String, simply ignores the “error”
  • Role Generate binds to class ThrowStatement to make sure the correct bytecodes for creating a RuntimeException are generated

Also, in the Outline you see both kinds of method bindings that are supported by Object Teams:

  • getExceptionType/setExceptionType are getter/setter definitions for field ThrowStatement.exceptionType (callout-to-field in OT/J jargon)
  • Things like “adjustType <- after resolve” establish method call interception (callin bindings in OT/J jargon – the “after” is symbolized by the specific icon)

The actual implementation is really simple, like (full listing of the first role):

protected class DontReport playedBy ProblemReporter {
        cannotThrowType <- replace cannotThrowType;
 
        @SuppressWarnings(&quot;basecall&quot;)
        callin void cannotThrowType(ASTNode exception, TypeBinding exceptionType) {
                if (exceptionType.id != TypeIds.T_JavaLangString)
                        // do the actual reporting only if it's not a string
                        base.cannotThrowType(exception, exceptionType);
        }
}
 

The base-call (base.cannotThrowType) delegates back to the original method, but only if the exception type is not String. The @SuppressWarnings annotation documents that not all control flows through this method will issue a base-call, a decision that deserves a second thought as it means the base plugin (here JDT/Core) does not perform its task fully as usual.

Intercepting resolve has the purpose of replacing type String with RuntimeException so that other parts of the Compiler and the IDE see a well-typed structure.

The method that performs the actual work is generateCode. Since this method is essentially based on the original implementation, the best way to see the difference is (select either the callin method or the callin binding):
Compare Menu
which gives you this compare editor:
Compare Editor
This neatly shows the two code blocks I inserted, one for creating the RuntimeException instance, the other for invoking its constructor. Or, if you just want to read the full role method:

/* This method is partly copied from the base method. */
@SuppressWarnings({"basecall", "inferredcallout"})
callin void generateCode(BlockScope currentScope, CodeStream codeStream) {
        if ((this.bits &amp; ASTNode.IsReachable) == 0)
                return;
        int pc = codeStream.position;
        // create a new RuntimeException:
        ReferenceBinding runtimeExceptionBinding = (ReferenceBinding) this.exceptionType;
        codeStream.new_(runtimeExceptionBinding);
        codeStream.dup();
        // generate the code for the original String expression:
        this.exception.generateCode(currentScope, codeStream, true);
        // call the constructor RuntimeException(String):
        MethodBinding ctor = runtimeExceptionBinding.getExactConstructor(new TypeBinding[]{this.stringType});
        codeStream.invoke(Opcodes.OPC_invokespecial, ctor, runtimeExceptionBinding);
        // throw it:
        codeStream.athrow();
        codeStream.recordPositionsFrom(pc, this.sourceStart);
}
 

You may also fetch the full sources of this little plug-in (plus a feature for easy deployment) to play around with and extend.

Next?

Ralf mentioned that he’d like to play with ways for also extending the syntax. For a starter on how this can be done with Object Teams I recommend my previous posts IDE for your own language embedded in Java? (part 1) and part 2.

Advertisements

Written by Stephan Herrmann

September 12, 2010 at 13:31

2 Responses

Subscribe to comments with RSS.

  1. oh that’s nice 🙂

    Jan

    October 19, 2010 at 08:53

  2. […] each new release it is good to test compatibility with older software. So I loaded my previous experiment (”project medal”) into the new milestone. Much as I expected: that little adaptation of the JDT still works as […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: