[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-dev] Multi-language support in the model and for preferences
|
While this is still fresh in my memory, I want to explain what I did in
Photran to add Fortran elements to the C Model and for adding new core
preferences. Comments are extremely welcome.
- For the model...
Everything inside our translation units is a subclass of
public abstract class FortranElement
extends Parent
implements ICElement, IParent, ISourceReference {...}
Yeah, not variables are not technically Parents, but it's not hurting
anything.
One thing that would be nice would be to have a class somewhere between
SourceManipulation and Parent. I ended up copying lots of methods
directly out of SourceManipulation into FortranElement... I would have
subclassed SourceManipulation instead of Parent, except our refactoring
is not (will not be) done via ISourceManipulation, so it would be
claiming we can do more than we really can.
I wanted our elements to have their own icons. I didn't want to add
more stuff into CElementImageProvider. Generally speaking, when you're
comparing based on type (which is happening all over the place in that
file), you would be better off taking advantage of polymorphism/dynamic
dispatch. (Comparison based on type is a typical "code smell"... see
Fowler's Refactoring book, page 255.) My solution was to give each
FortranElement a method
public ImageDescriptor getBaseImageDescriptor()
My only change to CElementImageProvider, then, was to add at the top of
getBaseImageDescriptor:
if (celement instanceof FortranElement)
return ((FortranElement)celement).getBaseImageDescriptor();
Theoretically, that method could be reduced to one line if every
CElement did this. :-)
One architectural flaw with this is that FortranElements (which are in
the core) must know what their icons are (which is typically the UI's
problem). Maybe it would be better if the elements only knew their
filename, and the CElementImageProvider used that to load an icon. Or
it could reflectively look at the CElement class name and grab an icon
with that name + ".gif", if it exists. I don't know. At any rate,
there is a circular dependency between the core and the UI here, which
needs to be dealt with.
Finally, I set the type field (setElementType()) to -1 in every
FortranElement. Is there any advantage to telling the model what's a
function, etc.? Similar to the above, I am not going to add more
constants to ICElement, so if that type field is important, it should
probably be eliminated, and tests against it should be replaced with
polymorphic calls back to the CElement. And/or ICElementVisitor needs
to become a real GoF Visitor (i.e., use double dispatch), and all of the
gigantic switch statements on types
(ChangeCollector#getAllTypesFromHierarchy, TypeSearchScope#add,
CSearchScope#add, etc.) need to become visitor instantiations. On the
other hand, if every language except C and C++ can just set the type to
-1 or an existing constant and be satisfied, then everything's fine
as-is. :-)
On a somewhat related topic, just out of curiosity, does the C/C++
Browsing perspective only use the model to populate itself, or does it
use more than that? Even after setting the type fields logically (e.g.,
class inside a namespace inside a translation unit), it didn't magically
populate itself... I only got a global namespace for each file.
Obviously, I haven't tried to track down what's happening there...
suggestions are welcome...
And do we have any hope of reusing the C indexer? Haven't looked at
that either...
- Preferences
I want the core to be able to initialize all of its Fortran-specific
preferences without telling it what they are. :-) So CCorePlugin.start
has only one line added:
FortranPreferences.initializeDefaults(getPluginPreferences());
The FortranPreferences class is just a bunch of constants of type
FortranPreference. Each FortranPreference has a setDefault(...)
function. So FortranPreferences.initializeDefaults just reflectively
calls setDefault on each of its fields. So adding a new Fortran
preference is simply a matter of adding a new constant to that class.
It gets its default value set automatically.
I don't think that will be an issue with multi-language support, since
we'll be adding new plugins, each of which can set its own preference
defaults however it wants. But I thought I'd mention it anyway.
Again, comments are welcome.
Jeff