Adding static imports to XExpressions scope [message #1006815] |
Sat, 02 February 2013 11:23 |
Alan Alberghini Messages: 19 Registered: January 2013 |
Junior Member |
|
|
Hi everybody.
I designed a simple domain-modelling language where one can specify Junit test cases for some entities.
The whole thing works ok, but I'd like to add some finishing touches (if possible) to make it more user-friendly:
- As thing are now, when one wants to write down a test case in my DSL, he has to write down something like this:
test aSillyTest {
junit::framework::Assert::assertEquals (1, 1)
}
The code after the test name is, in the grammar, a XBlockExpression.
How can I tell XBase that it should statically import junit.framework.Assert.* so those "assertX" methods are more easily accessible to the user while writing down tests using my DSL?
What I tried till now was overriding the "getImplicitImports" method in the scope provider, but that is useless in my case because JUnit is already in the build path and, consequentially, its classes are already in the scope of the project.
- How can one make it so, when the Xtext nature is added to the project when first adding a ".mydsl" file to it, Eclipse also loads (or suggests to load) the XBase library and JUnit4 (those bundled with the IDE itself) to the build path? Is there an easy way to do it?
Any insight is greatly appreciated.
|
|
|
|
|
|
|
Re: Adding static imports to XExpressions scope [message #1007328 is a reply to message #1006996] |
Tue, 05 February 2013 14:43 |
Alan Alberghini Messages: 19 Registered: January 2013 |
Junior Member |
|
|
Understood... Will try to look into it better as soon as I can get some time to think about it.
Meanwhile I got the second issue solved.
Here's what I did:
- Created a subclass of NatureAddingEditorCallback in the ui project
- Overridden "afterCreatePartControl(XtextEditor editor)", calling super and adding some code that changes the classpath
- Bound the new class in the MydslUiModule
Here's some code:
MydslUiModule:
public class MydslUiModule extends it.unibo.xtext.ui.AbstractMydslUiModule {
public MydslUiModule(AbstractUIPlugin plugin) {
super(plugin);
}
@Override
public Class<? extends IXtextEditorCallback> bindIXtextEditorCallback() {
// return super.bindIXtextEditorCallback();
return MyEditorCallback.class;
}
}
MyEditorCallback:
package it.unibo.xtext.ui.myproviders;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.xtext.builder.nature.NatureAddingEditorCallback;
import org.eclipse.xtext.ui.editor.XtextEditor;
@SuppressWarnings("restriction")
public class MyEditorCallback extends NatureAddingEditorCallback {
public static final String XTEXT_NATURE_ID = "org.eclipse.xtext.ui.shared.xtextNature";
@Override
public void afterCreatePartControl(XtextEditor editor) {
super.afterCreatePartControl(editor);
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
.getProjects();
for (IProject project : projects) {
try {
/*
* TODO: find a way to change the classpath only for projects
* using this plugin. Currently relying on the xtext nature, but
* it's too generic
*/
if (project.hasNature(XTEXT_NATURE_ID) && project.isOpen()) {
changeClasspath(project);
}
} catch (JavaModelException e) {
/*
* TODO: ignored for now as it is thrown when duplicated
* classpath entries are found.
*/
} catch (CoreException e) {
e.printStackTrace();
}
}
}
/**
* Changes the classpath of the given IProject adding the containers for
* JUnit4 and Xtend.
*
* @param project
* the project whose classpath is to change
* @throws JavaModelException
* if the classpath could not be read or written
* @author Lars Vogel
* (http://www.vogella.com/articles/EclipseJDT/article.html
* #jdt_classpath)
*/
private void changeClasspath(IProject project) throws JavaModelException {
IJavaProject javaProject = JavaCore.create(project);
IClasspathEntry[] entries = javaProject.getRawClasspath();
IClasspathEntry[] newEntries = new IClasspathEntry[entries.length + 2];
System.arraycopy(entries, 0, newEntries, 0, entries.length);
// add a new entry using the path to the container
Path junitPath = new Path("org.eclipse.jdt.junit.JUNIT_CONTAINER/4");
IClasspathEntry junitEntry = JavaCore.newContainerEntry(junitPath);
newEntries[entries.length] = JavaCore.newContainerEntry(junitEntry
.getPath());
Path xtendPath = new Path("org.eclipse.xtend.XTEND_CONTAINER");
IClasspathEntry xtendEntry = JavaCore.newContainerEntry(xtendPath);
newEntries[entries.length + 1] = JavaCore.newContainerEntry(xtendEntry
.getPath());
javaProject.setRawClasspath(newEntries, null);
}
}
Now, every time I'm asked to add the Xtext nature to a project containing one of my DSL files those libraries are correctly added to the classpath.
As can be seen in the javadocs, I slightly modified some code found here to alter the classpath of a project.
For those wondering where I found those paths for the containers, I just took a look at the ".classpath" file (it is hidden in the packages view, you need to use the navigator view to see it in Eclipse) in a project that contained them in the classpath.
What bugs me is that this code performs a "blind" search for the project that's been just configured (the code is called whenever the xtext nature is added) and I couldn't find another way other than looking for open projects with the xtext nature in the workspace... Is there a better way to target only the "current" project?
[Updated on: Tue, 05 February 2013 14:49] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.05730 seconds