Closed jpasski closed 8 years ago
Successfully built on travis CI, closing.
This was the first time I worked with e4 menu additions. I still dunno if I'm doing the right approach with an e4 model fragment or not. I'm assuming some of the views I'm working with are still Eclipse 3.x based, so using a model fragment that hooks into the legacy component seems to make sense. Anywho, learned a lot!
As usual, vogella helped out :)
Had difficulties on getting pop-up menus to work. I tried the following:
popup:
popup:org.eclipse.ui.popup.any
org.eclipse.ui.popup.any
org.eclipse.ui.popup.any w/ after=additions
#PopupMenu
None of those worked. Some of that was me throwing spaghetti against the wall
to see what worked. What was really confusing is that org.eclipse.ui.popup.any
didn't work, which was the catch-all for 3.x I guess.
What did work was explicitly stating the target:
org.eclipse.ui.navigator.ProjectExplorer#PopupMenu
.Another one to try in the future:
org.eclipse.jdt.ui.PackageExplorer?after=additions
In all cases, these were added as a Menu Contribution on the element ID
org.eclipse.e4.legacy.ide.application
.
Another thing that was confusing is how visibility and core expressions worked. This was also the first time I used core expressions. Core expressions are still managed via Eclipse extensions. This expression did not work:
<extension
point="org.eclipse.core.expressions.definitions">
<definition
id="io.opensemantics.semiotics.extension.e4.expression.projectshow">
<with variable="selection">
<iterate>
<adapt type="org.eclipse.core.resources.IProject">
<test
property="org.eclipse.core.resources.open"
value="true">
</test>
</adapt>
</iterate>
</with>
</definition>
</extension>
I tried a bunch of incantations using selection
and other values, no change.
The magic that worked was this:
- <iterate>
+ <iterate ifEmpty="false">
It seems that an empty selection returned true by default. WTF...
As can be seen above, I also learned about property testers. Those are nifty!
I went with dynamic menu contributions. To pass data (strings) around, it
seemed the recommended approach is to use Eclipse Commands. The e4 model
fragment adds a command that requires a parameter. When the dynamic menu
creates sub-menus, it populates the sub-menu's command with a string value
that can be passed to the menu handler. This was all new too. I had some
false starts until I came across a good SO answer that called out the
use of MParameter
. I was using older API method calls IIRC that were not
very effective.
The documentation on menu item creation emphasizes not being computationally expensive, which makes sense. I.e., don't be doing a lot of silly things when the menu is being populated. This led to the next journey :)
With the menus, I didn't want any long-running code, so using some type of
pub-sub service makes sense. Eclipse has one via IEventBroker
, which
uses Eclipse dependency injection (DI).
DI uses magic to make annotations like @javax.inject.Inject
work when an
Eclipse context is available. What's cool about this is standard OSGi
declarative services (DS) can also be injected using such annotations.
However, the inverse is not true.
In a standard DS, the @Inject
annotation doesn't work, since, well, OSGi
doesn't define that annotation to mean anything. Also, that means a DS
can't use other Eclipse services like IEventBroker
, since those
assume an Eclipse context of some sorts.
I wanted to keep the DS as vanilla as possible and not tie it to Eclipse,
which meant not using IEventBroker
. No problem, EventAdmin
to the
rescue! The EclipseSource people compete with Vogella on providing great
Eclipse and OSGi documentation.
Anywho, when an IProject
is selected, its name is published via EventAdmin
.
An EventHandler
subscribes to the same topic and handles the flip side
of generating the correct EMF objects for the ECP project. This asynchronous
nature makes testing a bit more complicated, but at least meets the requirement
on not doing a lot of blocking operations when working with the menu / UI thread.
Also started using the OSGi log services here, again via an EclipseSource blog.
And got dirty with the ECP API! Speaking of which, I was previously using the EMFStore API directly. The ECP API is a better abstraction, focusing more on the projects the data. I was unsure on if I wanted to stay w/ ECP / EMFStore due to the odd bugs here and there I came across. I'm liking it more, the less ignorant I become.
Learned a bunch on OSGi capabilities via two blog posts by Dirk Fauth:
The problem I had is not all OSGi services in use declare they provide capabilities. This would lead to dependency resolution errors in either PDE or Tycho/p2, like so:
[ERROR] Missing requirement: io.opensemantics.semiotics.extension.integration.tests 1.0.0.qualifier requires 'osgi.service org.eclipse.emf.ecp.changebroker.spi.NotificationProvider 0.0.0' but it could not be found
This was really painful in the integration tests. Since the test run
configuration by default includes all workspace bundles, service providers
would be resolved, and the tests would pass (yay!). However, when running
with Tycho, the tests would fail (boo!). Dirk's testing blog post pointed
to Tycho documentation on how to make explicit what I was hoping would be
implicit. The extension provider test case pom.xml
needed to include such a
declaration:
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<configuration>
<dependency-resolution>
<extraRequirements>
<!-- https://wiki.eclipse.org/Tycho/Packaging_Types#eclipse-test-plugin -->
<requirement>
<type>eclipse-feature</type>
<id>io.opensemantics.semiotics.app.dependencies.feature</id>
<versionRange>[1.0.0,1.1.0)</versionRange>
</requirement>
<!-- not included in the app dependency feature -->
<requirement>
<type>eclipse-plugin</type>
<id>org.eclipse.emf.ecp.changebroker.provider</id>
<versionRange>[1.9.0,2.0.0)</versionRange>
</requirement>
</extraRequirements>
</dependency-resolution>
</configuration>
</plugin>
Regardless, the extension provider now includes the necessary metadata in the Manifest and also for p2. It's not ideal that they're manually managed (unlike bndtools).
Filed Eclipse bug 498602 for ECP on some of their bundles that could benefit from capabilities.
Learned some debugging trick for Tycho. Since I wanted everything in Eclipse, I had to create two run configurations: a Maven one for Tycho and a remote application one to debug. Kinda cumbersome.
Talking about cumbersome, I found it strange that the Maven run configuration requires the command line switches to be in the Goals section of the run configuration. Alas.
Additionally, got familiar with the Maven -pl '!submodule1,!submodule2'
command, like so:
-pl '!io.opensemantics.semiotics:io.opensemantics.semiotics.model.product'
Nice to speed up retesting!
Command line used: mvn verify -X -DdebugPort=8000 -l ../maven.log -f builds/io.opensemantics.semiotics.parent/pom.xml -pl '!io.opensemantics.semiotics:io.opensemantics.semiotics.model.product'
OMG, this really confused me a bunch. The target definition originally included
only one dependency from Orbit: JUnit. After adding Mockito, I was getting a
bunch of resolution errors around org.objensis
not being found:
[ERROR] Missing requirement: org.mockito 1.9.5.v201605172210 requires 'package org.objenesis [1.0.0,2.0.0)' but it could not be found
The vogella blog on Mockito refers to an older Orbit 2015 drop that includes "Hamcrest-core & Objenesis" in including in the plugin name. So I tried adding just that feature to the target definition. No love. It took me a bit to realize that the "Java Library for Object Instantiation" is the bundle I needed. Then pretty much every Hamcrest plugin needed to be included. This relates to split packaging, which is something I've heard of but not quite familiar. Regardless, got it working with some integration tests, now with the following:
<unit id="org.hamcrest" version="1.1.0.v20090501071000"/>
<unit id="org.hamcrest.text" version="1.1.0.v20090501071000"/>
<unit id="org.hamcrest.integration" version="1.1.0.v201303031500"/>
<unit id="org.junit" version="4.12.0.v201504281640"/>
<unit id="org.mockito" version="1.9.5.v201605172210"/>
<unit id="org.objenesis" version="1.0.0.v201505121915"/>
<unit id="org.hamcrest.library" version="1.1.0.v20090501071000"/>
From @jonpasski on July 2, 2016 16:35
Context Menu
Handler
Copied from original issue: OpenSemanticsIO/semiotics-main#37