IMP Users Guide
This document provides guidance on using IMP to define a customized
IDE
for a new language. It addresses the following topics:
The sections that are relevant to all IMP users are the
prerequisites, identifying a project for the language, creating a
language description, and creating a parsing service, and using you IMP
IDE. The other services indicated are more or less
optiona. Additional IMP services are under development and
will be addressed
here when they are ready for general use.
The discussion of the parsing service mainly addresses the case in
which LPG will be used to define the language grammar and generate
a lexer and parser. However, other approaches to grammar
specification and parser development can be accommodated in IMP, and
the treatment of most other topics here is independent of the manner in
which the parser is provided.
A note on procedure:
The steps through "creating a parsing service" are required for any IMP
IDE. The
subsequent optional steps may be pursued in any order.
A note on terminology:
The text below will refer to several of the classes generated by IMP
by simplified "generic" names, such as the "Plugin" class or the
"ParseController" class. As these classes are actually generated,
their names will typically be prefixed by the name of the language to
which they apply. Thus, if your language is called "MyLanguage",
IMP will generate classes for you that are called
"MyLanguagePlugin", "MyLanguageParseController", and so on.
A note on "SAFARI" versus "IMP" "SAFARI"
is the former name of the Eclipse IMP. Many of the Java or
Eclipse software entities that IMP comprises used to be named with
reference to SAFARI. The names of those entities are being
updated to refer instead to IMP. Similarly, this document used to
refer to many software entities by names based on SAFARI. The
document is likewise being updated to refer to these entities by names
based on IMP. Until the transition in names is complete, this
document may refer to renamed entities by their old names and to
entities that have not been renamed by their new names. As far as
we know, though, the old and new names should be directly analogous,
with "imp" substituted for "safari." We apologize for any
confusion this may cause.
Prerequisites
You must have a IMP installed in your workspace. For information
on installing IMP, please look at the
installation guide (which also
lists IMP prerequisites).
Since we assume here that LPG will be used to generate a parser for
the language, LPG must also be available in your workspace.
(Actually, you can't install IMP without installing LPG.)
Information on how to install LPG is also available in the
installation guide.
The IMP release includes some IMP-based IDEs, including those for LPG,
X10, and a preferences specification language. These may serve as
examples for how you might build your own IDE.
Identifying a
project for the language
The goal of this step is to set up an Eclipse
project for the development of IMP IDE for your new language.
A IMP IDE must be defined in a Eclipse plugin
project. Each IMP IDE must be defined in a separate
project. If you do not have a suitable plugin project
available as a home for the new IDE then you should create one.
A note about plugin classes: When you use
the Eclipse New Project wizard to create a new plugin project, the
wizard by default creates a package with the name of the project.
In that package the wizard creates a plugin class with a name of the
form "<ProjectName>Plugin.java." The Safari New Programming
Language wizard likewise creates a new package and plugin class, but
one that by default is named based on the programming language rather
than on the project. If you use the default values in each
wizard, you can end up with two plugin classes, each in a different
package.
There are two ways to avoid this. One is
just to give your project and language the same name. The other
is, during plugin-project creation, to override the default values and
give your plugin class and package a name that matches that of your
language. (With the latter approach it is possible to have the
name of the language be different from the name of the project in which
the language IDE is defined.)
(Also note:
There is a IMP wizard called "New Project Wizard" but this is a
wizard for creating project wizards, not a wizard for creating
projects.)
Creating
a language description
The goal of this step is to provide basic
information about
the identity and characteristics of the new language.
This step is accomplished entirely within a IMP
wizard; to run this wizard invoke:
"File" -> "New" -> "IDE Language
Support" -> "Programming Language"
A note on navigating these Eclipse
menus: Under the "New" menu you may need to select "Other
..." in order to get to the next item. Instead of following the
menus, you can type "Ctrl-N" to open the "New--Select a wizard" dialog
from which you may be able to select a desired item directly.
These comments apply to all of the menu-navigation instructions below.
In the "Programming Language" wizard, you must provide information for
the
following required fields:
- Project: Browse to or type-in the
name of your language project
- Language: Enter the name of the
language (which for now must be the same as the name of the project). This is the canonical name for your language,
by which it will be identified to various IMP services.
Within IMP it is case-insensitive.
- Description: The “description” field
is for the entry of a user-readable, user-sensible description of the
language. Enter whatever description you
think is appropriate.
- Extensions: The “extensions” field
is for the entry of file-name extensions that may be used for source
files in the language. Enter a non-empty,
comma-separated list of extensions (omitting dots and without spaces). The IMP services defined for your language
will be available for files with these extensions.
You may also provide information in the following
optional
fields:
- Synonyms: This is a comma-separated
list of alternative names for your language
- DerivedFrom: The “derivedFrom” field
should be the canonical name of the programming language, if any, from
which the
new language is derived. The "derived
from" language, if any, should be one for which there is already a IMP
IDE. It is used
within IMP for determining inheritance relationships when locating
language services for a given language (for example, locating an
appropriate editor if none is defined specifically for your language). If your language is derived from another
IMP-supported language then
this field should be filled in accordingly. If
your language is not derived from another IMP-supported language
then this field should be
ignored.
- Icon: This should be the project-relative pathname of an icon
that can be used in graphical interfaces to mark files in your language.
- URL: This is intended for the URL of
a web page that contains information about your language.
- Validator: The “validator” field can
be given the fully-qualified name of a class that can determine whether
a given input file actually contains text in the given programming
language. This class must extend the
LanguageValidator class
Hit “Finish” when you are done editing the various
fields in
the wizard. A IMP language
description extension will be created using the above information and
added to
the project’s plugin.xml file. This step
also updates the projects Plugin class (to extend IMPPluginBase,
among other modifications), or it will create a Plugin class if one
does not exist.
Creating
a parsing service
The goal of this step is to create a lexer and
parser for
the language. These can be generated
from lexer and parser grammars using LPG (which is provided with
the IMP release).
A IMP wizard generates skeleton files for
the lexer and parser
grammars, which then need to be completed by the user with specific
language
details.
Given the grammar files, the
lexer and parser can be generated automatically or
manually using LPG (in the form of lpg).
Generation may occur by means of a LPG builder associated with the
language project or by means of lpg run as an Eciplse external tool.
To run the wizard to generate the
skeletons for the lexer
and parser grammars, invoke
"File" -> "New" ->
"IDE Language Support" -> "Parser Services" -> "LPG Grammar
and Parser for UIDE".
In the wizard:
- Be sure that the proper names are
entered into the project and language fields.
(These may be filled in automatically or you may have to enter them
manually.) As these values are entered, reasonable
default values will be entered into other fields.
- If you wish, edit the "id" field to
specify a non-default extension ID for the parsing service.
- If you wish, edit the "name" field to
specify a non-default name for the parsing service. This parameter is
not presently used, but is intended to be the user-visible name for the
parser.
- If you wish, edit the "class" field to
specify a non-default fully-qualified name for the parse controller.
This class is used to give access to the token stream, AST, and so on,
to the various higher-level language services. (Note: A
parse controller is necessary, so this field should be given a usable
class name.)
- Hit "Finish" when done editing.
Finishing the “LPG Grammar and
Parser of UIDE” wizard
has the effect of adding a parser extension to the plugin.xml file in
your
language project. The wizard also
creates two packages in the source folder of the language project:
- The “parser” package (typically called
something like “languagename.safari.parser”): This
package is initially populated with one class and three grammar-file
templates. The grammar-file templates
include one “.g” file that contains the main parser grammar and two
“.gi” (“grammar include”) files, one for a keyword lexer and one for a
general lexer. The one class is
ParseController, which is the class through which parse-related
services and data are accessed by other IMP services.
This class will not compile initially because it depends on
additional parser-related classes that have yet to be generated.
You may also
discover that this package contains an empty Parser class.
This may be generated automatically if the LPG builder is
running automatically in your project (in which case it will be
triggered by the appearance of the grammar files).
- The “parser.Ast” package (typically
called something like “languagename.safari.parser.Ast”):
This package will be empty until the parser is generated. At that time, the package will be populated
with classes and interfaces representing the AST for your language and
with some related classes. (It is also
possible, by configuring the LPG options differently, to have these
types generated as members within the parser class. For this
document we assume that the AST is represented in its own package.)
Additionally upon finishing the wizard, the LPG
grammar-template file for your
language will open in the editor, and the structure of the file should
appear
in the "Outline" view.
The grammar files contain some
generally useful elements (including
directives to LPG regarding generation) and some simple
instructions for
completing the files. The files also
include
some example entries for a simple expression language.
You will need to edit these file as appropriate
for your language. A quickstart guide to LPG,
as well as links to additional documentation on LPG, is found here. As noted there, the LPG
grammar files make ample provision for the inclusion of custom
code in a generated parser.
The grammar files may be edited in any
order.
However, for purposes of generation, the general lexer depends on they
keyword lexer and the parser depends on the geneal lexer, so they
should be generated in that order.
Your language project should be configured to include the LPG
Grammar File Builder. This should happen automatically when you
run the parsing-service wizard. If for some reason your language
project is not configured to include the LPG builder, then you can
enable the builder by selecting the "Enable LPG Builder" in the
context menu for the project. If for some reason you want to run
LPG manually (which shouldn't usually be neecessary), you can find
information about that
here.
The LPG Grammar File Builder
If your language project is configured to include the LPG Grammar
File Builder, then the generation process should occur
automatically
whenever a project build is triggered (which may be automatically or
manually,
according to the configuration and use of Eclipse).
The builder may also be triggered whenever the grammar file is
changed. (Note: At
this time, changes to the ".g" file will trigger the LPG builder
but changes to the ".gi" files will not generally trigger the
builder. If
you change the ".gi" files then you will have to run lpg
manually.)
Notes about
compilation
The generated
parser classes will depend on lpg to compile, so lpg.jar should
be in
the build path for your language project. This file can be found
in the Eclipse "plugins" folder, under "lpg_1.0....."
If your grammar will define a type with a name that
duplicates one of the Java type names (such as “Number”), then you will
need to disambiguate references to this type in the parser (which can
be done by explicitly importing the corresponding AST node types for
your language). The Java compiler should make this evident to you.
Other approaches
If you have your own parser:
Since the goal of this step is to
produce a lexer and parser, if you already have a lexer and parser
that meet IMP requirements then these may be used directly.
The "Hand-written
Parser" wizard allows you to select an existing parser and
creates a corresponding parser extension in the plugin.xml file.
To work within IMP, any "hand written" or non-LPG-generated
parser should, at a minimum, implement the ILexer, IParser, and
IParseController interfaces in the org.eclipse.uide.parser package in
the org.eclipse.uide.runtime project
.
This will entail providing implementations for several additional types
defined by IMP or LPG. (Some of these, unfortunately, are
currently defined by concrete types, although we expect to provide
interfaces for these in the future.) Thus, at this time we
recommend the use of LPG to generate parsers for use in IMP.
NOTE: If
you have a parser that was generated by LPG but outside of IMP,
it should be relatively straightforward to adapt it to IMP.
If you have your own grammar:
If LPG is to be used to generate
the lexer and parser, but you already have grammars for the
language to be parsed, then these may be substituted into, or in place
of, the IMP-generated templates.
Of
course, the
resulting grammar files must be compatible with LPG.
Creating
a token-coloring service
The goal of this step is to
create a class that will support
coloring of tokens of different sorts when their text appears in the
editor
(for example, keyword highlighting).
IMP provides a wizard to generate a
skeleton class for this purpose; this class must be specialized by the
user according to details
of the language and goals for the editor. To run this wizard:
invoke
"File" ->; "New" ->
"IDE Language Support" -> "Editor Services" -> "Token
Colorer"
As before, in the wizard assure that the names of
your project and language
have been correctly entered into the appropriate fields.
If desired, edit the remaining fields. Hit "Finish" when done.
The Token Colorer wizard creates a
safari.tokenColorer
package containing a TokenColorer class. The
wizard adds a tokenColorer extension to
the plugin.xml file for the language project and opens the TokenColorer
class in
an editor.
The TokenColorer class has two
important methods: the
constructor, in which a set of TextAttribut's are created (which are
later
used to specify the text presentation for the various token kinds), and
the
getColoring(..) method, which returns the TextAttribute to be used for
the given
token kind.
As you can see, getColoring() calls
IToken.getKind() to
determine the token kind (represented by an integer) and uses that to
compute
the correct text attributes. The set of valid token kinds is defined by
the
lexical analyzer; they are typically located in the LPG-generated
"Parsersym" interface (in the parser package) and generally start
with a prefix like "TK_".
The generated TokenColorer class
includes a few examples of
text attributes and token colorings based on the example expression
language
introduced with the grammar-file templates.
These may not compile as generated (due to inconsistencies with
the generated parser and AST) and will generally have to be tailored to
the language being defined.
The generated TokenColorer class is somewhat
dependent on LPG:
- The TokenColorer class implements a Parsersym interface that is
one of the standard, language-specific interfaces generated by LPG
- The getColoring(..) method takes an instance of an IToken, which
is defined in lpg.lpgjavaruntime
- The getColoring(..) method also takes an instance of an
IParseController; although this is defined by IMP, the default
implementation makes use of several types generated by LPG
As noted elsewhere, it is possible to implement these various
interfaces without using LPG (although it is the intention of IMP
to relieve the developer of this work by automating the
implementation using LPG).
Creating an outlining service
The goal of this step is to create a service that
provides an outline view of documents in your language.
As for the TokenColorer, there is a IMP wizard
that creates a skeleton class that contains the generic structure of
the outliner,
and this must be tailored to create an outliner for the specific
language being
defined. To run this wizard, invoke
"File" -> "New" ->
"IDE Language Support" -> "Editor Services" ->
"Outliner"
In the wizard, as before, assure that
the names of your project and language are correct and, if desired,
edit the remaining fields. Hit
"Finish" when done.
The Outliner wizard creates a
safari.outliner package
containing an Outliner class (and an Images class).
The wizard also adds an outliner extension to
the plugin.xml file for the language project and opens the Outliner
class in an
editor.
The Outliner class only has one
important method: createOutlinePresentation(),
which typically
retrieves the current AST (from an IParseController) and then visits
the AST, populating
the outline tree with various TreeItems corresponding to AST nodes of
interest. The visiting is done by an
instance of the
OutlineVisitor class, which is a member of Outliner and extends the
AbstractVisitor class.
The AbstractVisitor class contains
default visit(..) and
endVisit(..) methods for all node types in the AST.
These methods will traverse the AST but
otherwise have no effect. The
AbstractVisitor class is usually located in the “parser.Ast” package
or—depending
on parser-generator options—it may be contained as a member class
within the
generated parser class.
Some example visit(..) methods for the
simple expression
language are shown in the generated Outliner.OutlineVisitor class
(which may
prevent the generated file from compiling).
These must be adapted for the specific language being defined.
To add a program entity to the outline,
in the
OutlineVisitor class simply override the default visit(..) method
corresponding
to that type of AST node. Most
overriding methods will call createSubItem(..) with an appropriate
label. The visit(..) method should return
true (or
false) depending on whether the children of the node should be visited
(or not). When an item label is created it
is pushed
onto a stack. Thus, whenever a default
visit method is overridden to create an item label, the corresponding
endVisit(..)
method should also be overridden in order to pop the item label from
the stack. Note that items that are inherently childless do not
need to be pushed onto the stack, and if these items are not pushed
onto the stack then it is unnecessary to override endVisit(..) for them.
It will also be necessary to have
one visit(..) method that
calls createTopItem(..) to create a root for the outline.
(It will also be necessary to have a corresponding endVisit(..)
method.) This may be for some high-level node type
(such as “program”) or it may be given a label that does not correspond
to a
specific node type.
The generated Outliner class is somewhat dependent
on LPG:
- The TokenColorer class implements a Parsersym interface that is
one of the standard, language-specific interfaces generated by LPG
- One of its central methods (to set the outline tree) makes use of
IToken, which is defined in lpg.lpgjavaruntime
- The createOutlinePresentation(..) method takes an instance of an
IParseController which, although it is defined by IMP, has a default
implementation that makes use of several types generated by LPG
As noted elsewhere, it is possible to implement these various
interfaces without using LPG (although it is the intention of IMP
to relieve the developer of this work by automating the
implementation using LPG).
Creating
a text-folding service
The goal of this step is to create a service that supports
the folding of hierarchical syntactic elements in text editors for the
language.
As with the outlining service,
the IMP
wizard for text folding creates a skeleton class that contains the
generic
structure to support text folding and this class must be tailored to
the
specifics of the language being defined.
The IMP wizard that does this
is called “NewFoldingUpdater.” To run this
wizard, invoke
"File" -> "New"
->
"IDE Language Support" -> "Editor Services" -> "Source
folding updater"
As before, in the wizard assure that the names of
the project and language are correct and, if desired, edit the
remaining fields.
Hit "Finish" when done.
The NewFoldingUpdater wizard creates a
safari.foldingUpdater
package containing a FoldingUpdater class.
The wizard also adds a folding updater extension to the
plugin.xml file
for the language project and opens the FoldingUpdater class in an
editor.
FoldingUpdater contains one main
method,
updateFoldingStructure(..). This method
obtains the current AST and sends it a new AbstractVisitor. This visitor should contain a visit method
for each AST node type for which folding is desired.
Each visit method should simply call
AbstractVisitor.makeAnnotation(..) with its given node.
(An example is shown in a comment in the generated
FoldingUpdater code.) The
method makeAnnotation makes an annotation that spans the text
represented by
the node, and it is through the annotations that folding is enabled. The language-specific customizations required
for folding are simply to provide visit(..) methods for the AST node
types for which text is to be foldable.
These visit(..) methods should return true if folding should be allowed
for
nested units and false if not.
It may be necessary to add more complicated logic if more precise
control
of folding is desired, for example, if you wish to enable folding of
top-level blocks but not nested blocks.
Note: The NewFoldingUpdater
wizard requires the package and class names for the language AST node
type. The wizard currently assumes that
the AST node type has the default name and is located in the default
package. If these assumptions are not
valid, then
incorrect names for this package and class will be entered into the
generated
FoldingUpdater class. If that happens,
the class should be edited to fill in the correct names.
Creating
a hyperlinking service
The goal of this step is to create a service that supports hyperlinking
between regions of text in text editors for the
language.
Link sources and targets
typically correspond to entities defined in the underlying AST; common
examples include links from references to definitions, such as from
field references to field declarations or from class references to
class definitions. The link targets may be in the same source
file as the link source or in a different source file, depending on the
details of hyperlink semantics and implementation.
The IMP
wizard for hyperlinking creates two classes. One is a
HyperlinkDetector, the other is a ReferenceResolver. The
HyperlinkDetector contains a method detectHyperlinks(..) that is called
when it is necessary to check for hyperlinks. It makes use of a
ReferenceResolver to find the target, if any, for the current candidate
link source. The HyperlinkDetector is largely
language-independent; its only significant language dependence is on a
language-specific ReferenceResolver. The ReferenceResolver is
highly language specific, since it involves recognizing
language-specific link sources and identifying language-specific link
targets according to language-specific semantics. Typically
the generated HyperlinkDetector does not require user modification and
can be used directly as generated. The ReferenceResolver is
essentially template that will require some user programming, possibly
considerable. (As generated it compiles but does nothing
useful.) The amount of programming required to complete the
ReferenceResolver may depend on the functionality provided by avaliable
language tools such as a compiler. In other words, if available
language tools already support reference resolution, then the
ReferenceResolver may just need to retrieve the relevant information
from these tools. On the other hand, if the available language
tools do not support reference resolution, then the ReferenceResolver
may need to encode the logic necessary to perform resolution.
The IMP wizard to generate the
hyperlinking service called “NewHyperlinkDetector" and is run by
invoking
"File" -> "New"
->
"IDE Language Support" -> "Editor Services" ->
"Hyperlink Detector"
In contrast with some of the other language
service implementations, the ReferenceResolver does not (at least by
default) rely on a visitor to the AST. The principal methods to
be implemented are getLinkTarget(node) and getLinkText(node). The
user can also implement methods that will perform filtering on given
link source nodes to eliminate nodes that aren't appropriate in that
role.
Note:
The as with the NewFoldingUpdater
wizard, the NewHyperlinkDetector wizard needs the name of the package
that contains AST node
types.
If the value provided by default is
not
valid, then
the class should be edited to fill in the correct name.
Creating
a builder service
The goal of this step is to create a
builder for the
language. Builders perform activities
like generation or compilation for files in a particular source
language. Builders in Eclipse are
associated with
projects in a many-to-many relationship.
When a project is built, the various builders for the project
are
invoked, and each builder performs its respective build action on files
in the
project that have the appropriate type. The
IMP NewBuilder wizard generates a Builder class that must be
customized to
perform the desired language-specific build activity.
To invoke the NewBuilder wizard, select
"File" -> "New" ->
"IDE Language Support" -> "Core Services" ->
"Incremental builder"
In the wizard:
- Assure that the names of the project
and language are entered correctly
- Although it is not necessary to define
a nature to which your builder will be associated, this is a fairly
common practice. Whether
a builder is configurable depends on the design of the particular
builder. If the values for "hasNature" and
"isConfigurable" are left blank then they are treated as if false.
- Although the parameter "name" and
"value" fields are required here, they need to be given meaningful
values only if your builder will make use of external information
(which is not necessary for many builders). The requirement for
these fields is a current limitation that we expect to relax in the
future.
- Hit "Finish" when done.
The NewBuilder wizard generates one package, two classes,
and three plug-in extensions, and it brings up one of the classes, the
“Builder” class, in an editor.
The package that is generated is the
“safari.builders”
package. It contains the two generated
classes,
a “Builder” class and a “Nature” class.
The new extensions are a builder extension (extending
org.eclipse.core.resources.builders),
a nature extension (extending org.eclipse.core.resources.natures), and
a
problem-marker extension (extending org.eclipse.core.resources.markers). All of these classes and extensions are
created regardless of the values provided to the wizard (in particular,
regardless of whether "hasNature" is true or false)..
The problem marker defines a type of marker
annotation that the builder can attach to source files to represent
problems
encountered when building the files.
The Builder class is a skeleton that
overrides or implements
several methods defined in its abstract parent class, IMPBuilderBase:
- getErrorMarker(..)
- getInfoMarker(..)
- getWarningMarker(..)
- getPlugin(..)
- isSourceFile(..)
- isNonRootSourceFile(..)
- isOutputFolder(..)
- compile(..)
Most of these methods as generated will
do reasonable things
(although you may tailor any of them if you find a need to do so).
The method isNonRootSourceFile(..) is used to
identify files (like C/C++ ".h" files or LPG ".gi" files) that
should not be compiled directly but that should nevertheless be
processed for dependencies.
In any case you will have to edit the
compile(..) method,
which is really the main “build” method.
This will have to call your “compiler” in an appropriate way for
a given source file, retrieve any diagnostic messages that result from
the building, and create problem markers
for those. If your build activity runs
in an external process, or uses java.io to create output files, you
will also
need to call IResource.refresh() on any folders that contain generated
output
files (assuming that they are somewhere in your workspace).
IMP defines an interface,
IMessageHandler (org.eclipse.uide.editor.IMessageHandler),
to facilitate the reporting of error (and other) messages from
compilers (or
other builders) to interested services. IMP
also provides an implementation of this interface,
MarkerCreator
(org.eclipse.uide.builder),
that creates
marker annotations for messages received and attaches those to a given
source
file.
The figure below
shows the implementation of a Builder compile(..)
method using a LPG-generated ParseController in the role of the
compiler
and using MarkerCreator to handle parser error messages and create
marker
annotations on the given source file.
The Nature class extends
org.eclipse.uide.core.ProjectNatureBase
and provides some simple method implementations and stubs.
These can be used as-is without further
modification unless more sophisticated control over building is
required for
the nature. (With a new nature this is
not likely to be true initially.)
The builder extension will be generated
to contain elements
representing the various fields from the wizard. The
nature extension will be generated with a
“builder” element that refers to the generated builder extension. (This happens regardless of whether
“hasNature” was set to true in the wizard, but the nature need not be
applied
to any project that contains files in the source language, and the
builder for
the language can be used independently of the nature).
In the marker extension a marker with id
“problem” is defined with super type
“org.eclipse.core.resources.problemmarker.” (Marker
types are maintained as in this way as metadata.)
A note on Annotations and Markers
When a SAFARI editor runs, the source text is
parsed frequently and error messages are reported as annotations that
appear in the editor. These annotations are not associated with
the
source file and do not appear in the "Problems" view. When a
SAFARI Builder runs, the editor annotations are deleted and a new set
of marker annotations are created. These annotations also appear
in the editor (and may seem identical to pre-build editor
annotations). However, the marker annotations are
associated with the file and do appear in the "Problems" view.
Building may occur automatically, whenever a file is saved (or a
project is cleaned), or building may occur manually, only when
explicitly invoked by the user. Regardless, problem markers will
appear when builds occur. When a file is opened in an editor the
problem markers are deleted but the file is parsed immediately and new
editor annotations are created.
Using your SAFARI IDE
To use your language and SAFARI IDE in a development project, you will
need to add a corresponding builder entry to that project's ".project"
file. If you have defined a nature for your language you may also
want to add a nature
entry to that project's ".project"
file. Once this is done, the services defined for editing and
building in the language should be automatically available for files
identified with the extensions given in the language description.
Final words of advice
Be careful entering information
into the wizards. The wizards will generally not let you
get away without providing information for required fields, but they
(and the rest of SAFARI) are not necessarily robust with respect to
errors in the provided information. Errors in the provided
information may or may not show up directly and may or may not have
confusing effects.
You can update some of the SAFARI
information manually. While the wizards are intended to
facilitate the entry of necessary (or at least useful) information at
appropriate times and places, you can also manually edit the plugin.xml
file to set (or reset) many of the attributes associated with SAFARI
extensions. So, if you want to add an icon or validator to an IDE
that is already defined, you can do that without rerunning the
wizard. (This can help to avoid problems that can occur when the
wizards are rerun ...)
Be careful when rerunning the wizards!
- Several of the wizards generate skeleton files that must be
tailored by the user. If you rerun one of these wizards, the
tailored files will be clobbered and updates to them will be
lost. So backup these files where they won't be clobbered.
- Several of the wizards add extensions to the plugin.xml file of
the IDE project. Rerunning these wizards does not remove the
extensions created by previous invocations. So, if you want to
rerun one of these wizards, you should manually delete the
corresponding extension(s) from the plugin.xml file.