Flexible Project Structure in e4
While the Eclipse e4 project is currently placing on emphasis on strengthening the Eclipse platform as a generic application framework, Eclipse maintains its primary function as an integrated development environment.
In the past developers have had to deal with a lack of flexibility in the Eclipse IDE, when it comes to the requirements of complex development projects. In this article, E4-committer Serge Beauchamp discusses how e4 will bring more flexibility to the project management structure.
An IDE project consists of an organized set of files and their meta information that can be used to achieve a particular task (such as building an executable.)
Traditionally, C/C++ IDE projects have consisted fundamentally of a simple list of files recorded hierarchically. C/C++ IDEs such as Metrowerks CodeWarrior and Microsoft Visual Studio are a good example of such an approach to working with projects.
But the Eclipse IDE was initially designed to support java development, therefore its original project engine has different roots.
In contrast with C based languages, in java there is a tighter integration between the java classes and the source files that contain them. In order for the java compiler to find the class definitions, the source file typically has the same name as the public class it contains, but more importantly java classes must be located in source files that exist in file system directories which have the same name as their package names.
The only flexibility with javac is to specify classpath directives, but this does not alleviate the basic restriction of having to keep java source files in directories according to their package names.
So for Java developers, the source file organization is much more rigid than in C based languages, where locating source files is not an issue (all sources must be explicitly passed to the compiler) and header files are either relative to the source files themselves, or relative to given include paths. C/C++ developers tend to host source files in a complex web of directories based on many factors, including release engineering, componentization, team cooperation, and development history.
Because of this directory/package-name restriction, Eclipse as a java IDE did not need to support a very flexible project structure, and in its early releases it simply displayed the straight representation of the project directory on disk.
This design quickly became inadequate for using Eclipse as a more general tool IDE, so many features were added over the years to give Eclipse projects a more flexible project structure, such as linked resources.
But even in the latest Eclipse Platform release (Galileo,) the Eclipse project file management is still problematic when it comes to working with files located outside of the project directory.
The main limitations are the following:
Virtual project file structure
The existing resource primitives in Eclipse do not fully allow the user to create truly arbitrarily complex file structures in projects. The limitation is that in order to create a given hierarchy, the only container objects available are the folders and linked resource folders. Unfortunately, both require an actual folder located on the file system; the only difference between them is whether their parent in the workspace tree is the same as their parent in the file system.
To alleviate this limitation, e4 now supports Groups. A group is a container (seen by the API as a normal IFolder resource) that has no location in the file system. Because of this, only linked resource files and folders can be created under a group.
Groups appear in resource navigators as purple folders, to distinguish them from regular folders.
The project explorer has been made group-aware, so that normal drag and drop operations in the project explorer where the target is a group are handled in the most appropriate way. For example, when the user drag and drops a normal file resource on a group, instead of simply giving an error, a linked resource pointing to the original file is automatically created.
The first requirement when recording a list of files in a project, is that the file’s location has to be recorded in a way that is portable across computers.
Until Galileo, the mechanism to record linked resources relied on a workspace level list of variables, and the user specified the relative linked resource location. Because this variable list was maintained in the workspace .metadata folder, along with a myriad of user settings, using linked resources in a project practically made the project non-portable across computers and even across workspaces on the same computer.
In e4, projects now store their own path variable list in the .project file. A new property page, available in the project Properties, allows the user to see and edit the path variables. Default path variables are available for all projects, including PROJECT_LOC, which is automatically initialized to the project directory location.
Third party plugins can also extend the default project path variable list through the variableProviders core.resources extension point.
Ease of use
One of the main obstacles to the use of linked resources in Eclipse is the tedious process of creating linked resources, which require the user to go through the new file/folder wizard, and create linked resources one by one; specifying the location each time.
In e4, the user is now able to create linked resources simply by dragging and dropping from the OS shell (i.e. Windows Explorer) into the workbench project explorer. A dialog then appears, letting the user choose which type of resource should be created.
The first choice consists of the legacy Eclipse behavior: copying all the files under the target location. The second choice allows the user to automatically create a hierarchy of groups and linked resources files, mimicking the file system hierarchy.
The third will generate only linked resources for each file and folder contained in the drag source, without creating any groups.
When linked resources are created, the user can allow Eclipse to automatically generate the location as relative to the most appropriate variable (typically PROJECT_LOC), or explicitly select the variable where the linked resources locations should be created.
Many changes have been implemented to make linked resources a first class workflow in Eclipse. One of those changes is allowing the user to change the location of a linked resource from the resource property page.
Another improvement is the ‘Linked Resource’ editor in the project property page, where the user can view all the project’s linked resources in one convenient location, grouped by their location error status. Here, the linked resource location can be converted automatically, variables created, and locations changed.
Another new feature in e4 is the resource filters.
Resource filters allow the user to configure which file system resources will be visible to the Eclipse workspace tree when a refreshLocal() is performed. The user can create include-only filters, exclude-all filters, and specify if these apply to files, folders, or both. They can also be set to be inheritable, so all children of a given container will inherit the filters automatically.
The filters run at the lowest level of the core.resource API, so that resources can exist in file system hierarchies containing tens of thousands of files without taxing the core.resource plugin with a penalizing memory and performance overhead.
Only normal file and folder resources that are implicitly populated in the workspace tree by the refresh mechanism are subject to the resource filters. Because the user explicitly creates linked resources and groups, the resource filters do not apply to them.
Resource filters can be specified on a group resource, but they will be effective only as far as they are set to be inheritable, and apply only to the group’s children that are linked in the resource folder.
Resource filters can also be specified on a container before the container is created (either in the new resource wizard, or programmatically), so that the initial refresh() will be filtered appropriately.
New filter types can also be added through the filtersProviders core.resources extension point.
All the new e4 features are fully compatible with the existing Eclipse 3.x API contracts. All plugins that use the existing core.resources APIs will transparently work in workspaces and projects that are using the new e4 features, including groups, project path variables and resource filters.
The only subtle difference, is that groups are seen by the plugins as linked resource folders that always return null when IResource.getLocation() and IResource.getLocationURI() are called.
Since this was already a valid return value for those APIs, if a 3.x plugin already handled this properly, it will work transparently in e4.
Many improvements are still being discussed in the core.resources, including automatic project provisioning, project reference overhaul using linked resources, performance improvements when serializing the .project file, etc…
Using the new Linked Resources APIs
One can imagine that, if the e4 core.resources features were made available in Eclipse 1.0, many IDE features would have been implemented differently.
For example, the JDT Java Build Path/Libraries feature duplicates many of the basic linked resource features to locate .jar files, and this would have conceivably been implemented differently.
Similarly, e4’s comprehensive and flexible set of APIs for managing project resources widens the domains where the core.resource API can successfully be used.