Sharing Parse Trees

A syntax-highlighting tool, a lint tool running in the background, and a user-activated refactoring tool all use parse trees for the code. Each requires parse trees for partially overlapping sets of the code.

What interface should provide this service?

The lint tool matches each method parse tree against a rich set of patterns that each represent a potential problem. Requesting a fresh parse tree each time can lead to performance problems. If the lint tool deals with these problems by caching, how should the system deal with changes in the code?


I strongly believe that the parse tree data structure in the IDE should be designed using Model-View-Controller architecture. The parse tree should be kept in a special repository ("parse tree service", or "front-end service"), which provides access to itself using a well-designed API surface. All other components, such as the editor, the compiler back-end, the debugger, the resolver, the type-inferencer, the completion engine etc. should operate on this data structure through the API surface only.

The editor should be a view on the code model: every time the text in the editor is correct and can be parsed without errors, the parse tree (the Model) should be updated using the Controller.

As every other Model, the parse tree service should be observable. That is, it should notify all clients, what has changed so that the clients that are listening could update themselves correspondingly.

I think that the MVC approach should solve the problem posed by Daniel - once a separation into observable model and listener views is made, it will be relatively easy to keep all the data structures consistent throughout the IDE.

My favorite example of where MVC could be useful is a bug in Visual Studio 2005, where you have a list of errors with line and column numbers, and when you add a new line to the code being edited, the line numbers in the error list don't get shifted. When you click on an error, you'll jump to the wrong location in code. If a MVC architecture was there, the error list would be a view on the code model, and it would update automatically every time the code would change.

So I vote for a single observable "front-end service" in the IDE which serves as a parse tree repository, where the most recent valid parse tree for each class/interface is stored.

What kind of events should this service possess? My first guess would be:

 * Compile unit added
 * Compile unit removed
 * AST node added
 * AST node deleted
 * AST node replaced
These are the atomic changes which could be composed to more complex transactions. Only the top-level transaction would actually fire a notification to the listeners. This transaction system could also provide the global Undo/Redo engine, so that the editor isn't responsible for Undo/Redo anymore. In the age of Refactoring, an editor of a single file shouldn't be responsible for Undo/Redo anymore, because the changes could be global to the project ("Rename class", "Move method", etc.)

Please let me know what do you think. Thanks KirillOsenkov


Last edited June 18, 2007
Return to WelcomeVisitors