Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Adding static imports to XExpressions scope
Adding static imports to XExpressions scope [message #1006815] Sat, 02 February 2013 06:23 Go to next message
Alan Alberghini is currently offline 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:

  1. 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.
  2. 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 #1006817 is a reply to message #1006815] Sat, 02 February 2013 06:57 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian Dietrich
Messages: 5847
Registered: July 2009
Senior Member
Hi,

guess you have to look at xtends source code.
org.eclipse.xtend.core.scoping.StaticallyImportedFeaturesProvider

for the second problem
use org.eclipse.xtext.builder.nature.NatureAddingEditorCallback as a starting point
and try to change .classpath as well
Re: Adding static imports to XExpressions scope [message #1006834 is a reply to message #1006817] Sat, 02 February 2013 11:52 Go to previous messageGo to next message
Alan Alberghini is currently offline Alan Alberghini
Messages: 19
Registered: January 2013
Junior Member
Thanks for the pointers, Christian.
For now I didn't get nothing out of it, but I'll look again into it soon.
Re: Adding static imports to XExpressions scope [message #1006993 is a reply to message #1006834] Sun, 03 February 2013 12:15 Go to previous messageGo to next message
Alan Alberghini is currently offline Alan Alberghini
Messages: 19
Registered: January 2013
Junior Member
I got lost after traversing 15+ files trying to understand how the StaticallyImportedFeaturesProvider works, but a new idea popped into my mind: could it be possible to specialize ImportNormalizer to resolve and deresolve static methods/fields qualified names? Would this provide the same result as static imports in Java/Xtend?
Re: Adding static imports to XExpressions scope [message #1006996 is a reply to message #1006993] Sun, 03 February 2013 12:49 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian Dietrich
Messages: 5847
Registered: July 2009
Senior Member
Afaik the ImportNormalizer is for types => you would still have to write Assert::assertEquals
Re: Adding static imports to XExpressions scope [message #1007328 is a reply to message #1006996] Tue, 05 February 2013 09:43 Go to previous message
Alan Alberghini is currently offline 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:

  1. Created a subclass of NatureAddingEditorCallback in the ui project
  2. Overridden "afterCreatePartControl(XtextEditor editor)", calling super and adding some code that changes the classpath
  3. 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. Smile
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 09:49]

Report message to a moderator

Previous Topic:Strange Xtext error
Next Topic:How to obtain starting offset in textual representation of a model element?
Goto Forum:
  


Current Time: Thu Apr 17 23:36:57 EDT 2014

Powered by FUDForum. Page generated in 0.02178 seconds