Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 366020

Summary: [xtend] Support for try-with-resource
Product: [Tools] Xtend Reporter: Sebastian Zarnekow <sebastian.zarnekow>
Component: CoreAssignee: Project Inbox <xtend-inbox>
Status: CLOSED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: btickets, christian.dietrich.opensource, eclipse, info, joerg83reichert, lieven.lemiengre, lorenzo.bettini, max.bureck, moritz.eysholdt, st.oehme, sven.efftinge, tom.schindl
Version: 2.2.0   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard: v2.18
Bug Depends on:    
Bug Blocks: 457593    

Description Sebastian Zarnekow CLA 2011-12-08 07:51:07 EST
try(stream = new FileOutputStream(someFile)) {
  // do things with stream
}

We should consider this for Closables and AutoCloseables (on the contrary to Java) and always compile to try { } finally { } with a reasonable idiom in the finally block.
Comment 1 Sven Efftinge CLA 2012-03-08 03:07:49 EST
Alternatively we could introduce a library function taking a Closable or Autoclosable and a block:

tryWith(new FileOutputStream(someFile)) [
   // do stuff with it
]

Maybe with one (or two) overloaded variant for two (or three) closables.
Comment 2 Sebastian Zarnekow CLA 2012-03-08 03:30:01 EST
Having overloaded variants may lead to unclosed resources if we implement this as a library function:

tryWith(new FileOutputStream(fileA), new FileOutputStream(fileB)) [ .. ]

Assuming the second output stream cannot be created and the constructor throws an IOException, the first one will never be closed. That's why I favored the compilation to a real try .. finally instead of the library approach.

try(stream = new FileOutputStream(someFile)) {
}

could be compiled to

FileOutputStream stream = null;
try {
  stream = new FileOutputStream();
} finally {
  if (stream != null) {
    try { stream.close();
    } catch(IOException e) { .. }
  }
}

This pattern could be applied to more than one closable in the try(..) part.
Comment 3 Sven Efftinge CLA 2012-03-08 05:15:20 EST
I see. What if we pass in providers:

tryWith( streamOne(), [streamTwo()]) [
  a, b |
  // do stuff with a and b
]

It's admittedly isn't a totally nice syntax, but it's library and not a language feature, which is a huge plus IMHO.
Comment 4 Sebastian Zarnekow CLA 2012-03-08 05:25:01 EST
Since the provider for the second closable does not take any arguments, the syntax would be even worse:

tryWith( streamOne(), [|streamTwo()]) [
  a, b |
  // do stuff with a and b
]

Furthermore anything that is used by the constructor of streamTwo has to be final in the method body. Therefore I think it would be ok to use nested tryWith invocations for the rare case of having two closables at hand

tryWith(streamOne()) [ first |
  tryWith(streamTwo()) [ second |
    .. do the hard work here
  ]
]

Since we have sneaky throw for Xtend, it should work well enough:

try {
  tryWith(newStream()) [ // this save the finally dance in the surrounding try
  ]
} catch(IOException e) {
  // alert, log, do whatever you like
}

and it's not too bad compared to a first class support for new instances as 'argument' for the try block:

try(newStream()) {
  // hardwork with 'it'
} catch(IOException ioe) {
  // logging
}
Comment 5 Sven Efftinge CLA 2012-03-08 05:36:46 EST
(In reply to comment #4)
> Since the provider for the second closable does not take any arguments, the
> syntax would be even worse:
> 
> tryWith( streamOne(), [|streamTwo()]) [
>   a, b |
>   // do stuff with a and b
> ]

That depends on how we define the signature ;-)

> 
> Furthermore anything that is used by the constructor of streamTwo has to be
> final in the method body.

Since final is the default in Xtend anyway I don't consider this a problem.

> Therefore I think it would be ok to use nested
> tryWith invocations for the rare case of having two closables at hand
> 
> tryWith(streamOne()) [ first |
>   tryWith(streamTwo()) [ second |
>     .. do the hard work here
>   ]
> ]

Looks good and is even simpler. :-)
Comment 6 Sebastian Zarnekow CLA 2012-03-08 08:53:32 EST
Alternativly we could make this an implicit extension method instead of a tryWith(..) routine:

new FileOutputStream(..).closeAfter [
  // do something with *it*
]

It would probably need a better name, though.
Comment 7 Sven Efftinge CLA 2012-03-08 09:17:45 EST
Yes, that's nice and I also like the name.
Comment 8 Sebastian Zarnekow CLA 2012-05-22 16:24:47 EDT
Alternatively we could use one of the operators, e.g

new FileInputStream(myFile) => [
  processStuff()
]

or 

new Reader(..) >>> [ ]
Comment 9 Stefan Oehme CLA 2014-08-04 03:13:59 EDT
We just talked about this some more and decided that we should go with the language feature instead of the library method, because:

1. The syntax gets awkward for more than one closable
2. Having more than one closable is pretty common (OutputStream => OutputStreamWriter => BufferdWriter)
3. The AutoClosable interface was only introduced in Java 1.7
Comment 10 Michael Vorburger CLA 2016-04-26 15:11:57 EDT
+1 .. just found this, would be nice to have this now?

In the mean time, https://github.com/dslmeinte/Xtend-utils/blob/master/Xtend-util/src/nl/dslmeinte/xtend/resources/ResourcesUtil.xtend looks neat.
Comment 11 Lorenzo Bettini CLA 2016-10-13 13:16:11 EDT
I implemented try-with-resources in Jbase (https://github.com/LorenzoBettini/jbase/pull/60).

If there's still interest in supporting try-with-resources in Xbase I can work on that (hopefully, it should be rather straightforward now that I know where to put my hands on :)
Comment 12 Michael Vorburger CLA 2016-11-01 15:32:07 EDT
> If there's still interest in supporting try-with-resources in Xbase

Hi Lorenzo, FYI I personally currently use Xtend less than I used to when writing the comment above - but generally speaking the feature still seems like a nice to have...
Comment 13 Lieven Lemiengre CLA 2017-08-11 08:10:07 EDT
I often miss this feature...
Comment 14 Christian Dietrich CLA 2018-03-24 11:32:39 EDT
see https://github.com/eclipse/xtext-xtend/issues/395
Comment 15 Max Bureck CLA 2019-04-18 10:51:07 EDT
The GitHub issue is closed (https://github.com/eclipse/xtext-xtend/issues/395), I am simply closing this bug accordingly, if you don't mind 😀