Source code file content

Revision: 2

import
» Project Revision History

» Checkout URL

web-content / trunk / docs / code-assistance-architecture / code-assistance-architecture.html

Size: 19060 bytes, 1 line
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
    <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1251">
    <title>NetBeans C/C++ Development Pack Code Assistance Architecture</title>
    
    <STYLE type="text/css">
        H1 { text-align: center}
        H2 { text-align: center}
        H3 { text-align: center}
        H4 { text-align: center}
        H5 { text-align: center}
    </STYLE>
 
</head>
<body>

<H1>NetBeans&trade; C/C++ Development Pack<br>Code Assistance Modules Architecture</H1>

<p>This document describes the architecture of the modules that provide code assistance functionality.
By code assistance we mean such features as code completion, 
hyperlink navigation, code folding, class view, etc.
</p>

<h2>Main Components</h2>

<h3>Main code assistance components</h3>

<p>The figure below shows the (simplified) relationships 
between code assistance components. 
Let us first introduce some terminology</p>

<h5><img src="code-assistance-overall-1.png"></h5>

<dl>
    <dt>Language Model
    <dd><p>The Language Model gives a developer 
    a programmatic way to see the source code.
    It is a set of interfaces that represent source code and these 
    interfaces implementation. These interfaces are to describe every detail 
    of the uderlying source code. It does not contain any user-visible features, 
    but is rather a basement for these features. 
    Language Model consists of the Language Model API 
    and the Language Model Implementation</p>
    
    <dt>Language Model API
    <dd><p>Language Model API is a set of interfaces 
    that represent the underlying source code.
    Those who write the end-user functionality that works with C/C++ source code
    use Language Model API and know nothing about how it is implemented.
    So we can switch to another parser, or start
    getting information from compiled code, or whatever - 
    this won't cause any changes in the code related with
    end-user funcionality.</p>
    
    <dt>Language Model Implementation
    <dd><p>The implementation of the Language Model API. 
    It will be described briefly in the next sections</p>
    
    <dt>Language Model Clients
    <dd><p>Language Model Client is code that uses Language Model API.
    All modules that provide particular code assistance features - 
    Code Completion, Class View, etc. are Language Model clients.</p>
</dl>

<h2>Language Model API</h2>
    
<p>As it was mentioned above, the Language Model API 
is a set of interfaces that represent source code</p>

<p>This API is experimental. There is no warranty that it will not be changed 
in subsequent releases.     Moreover, some changes most likely will be introduced 
in the next release. So the idea of this article is rather to describe 
the direction we are moving towards, than to encourage you writing plugins 
that are using this API right now.</p>

<p>You can surely do this on your own risk.
The ideology of the API will definitely survive; 
the experiece of the C/C++ Pack development team shows
that moving to the next Netbeans release
does not cause code rewrite; most likely 
you'll have to to make just several small changes in your code.
</p>

<h3>Main Building Blocks</h3>

<p>The API consists of a set of interfaces, an interface per each language consrtuct.
For example, a C++ class is represented via 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmClass.html">
CsmClass</a> interface, a C or C++ function is represented via
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmFunction.html">
CsmFunction</a> interface; each source file is represented via 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmFile.html">
CsmFile</a> interface, and so on.</p>

<p>There are also interfaces for statements (
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/deep/CsmStatement.html">
CsmStatement</a>) and expressions (
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/deep/CsmExpression.html">
CsmExpression</a>). For now (version 6.0) the expressions aren't implemeted well enough 
(they contain only top-level expression as a whole and do not return
the sub-expressions tree).</p>

<p>The "Csm" prefix stands for <b>C</b>/C++ <b>S</b>ource <b>M</b>odel.</p>

<p>The root of the API class hierarchy is a 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmObject.html">
CsmObject</a>. It acts as the common ancestor for all interfaces in the Language Model API. 

<p>Most interfaces that correspond top-level elements (classes and their members, functions, variables, etc)
are derived from 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmDeclaration.html">
CsmDeclaration</a>.</p> 

<p>Almost all interfaces in the API extends 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmOffsetable.html">
CsmOffsetable</a>. It represents an element that resides in a continuous segment of a single source file.
It allows to know, which file the given element resides in, 
and what are the start and the end position of the given elemet within that file.

The
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmOffsetable.html#getContainingFile()">
getContainingFile()</a> method returns the file that contains the given element and
a pair of method.
The
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmOffsetable.html#getStartOffset()">
getStartOffset()</a> and
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmOffsetable.html#getEndOffset()">
getEndOffset()</a> methods return the start and the end offset of the given construct in the file it resides in.
</p>

<p>The IDE project is represented via
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">
CsmProject</a> interface. One can ask, why don't we just use 
<a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-modules-projectapi/org/netbeans/api/project/Project.html">
Project interface from NetBeans API</a>. It's because 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">
CsmProject</a> has some specific functionality, such as 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html#getGlobalNamespace()">
getGlobalNamespace()</a> or
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html#waitParse()">
waitParse()</a> methods.

Apart from instaces that represent IDE projects, there usually exist several so-called "artificial" projects.
The latter acts as containers for header files that are used in some IDE project, 
though does not belong to any IDE project.
The examples are system headers from /usr/include.
Such artificial projects are also represented by instances of
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">
CsmProject</a> class. Usually one artificial project per include directory is created.</p>

<p>There is a special interface, which acts like a central point to the Language Model - 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModel.html">
CsmModel</a>. It allows you to add and remove listeners, 
get the list of open projects, and so on.</p>

<h3>Logical View and Physical View</h3>

<p>IDE graphical user interface has two representations of the program structure. 
When user opens a file, the Navigator shows this file structure. 
We call this <i>physical</i> structure, because it corresponds to the physical order 
of the declarations within the file.
IDE also has another view - Class View - which shows the structure 
of the entire project from language pomt of view. 
We call this <i>logical</i> structure.</p>

<p>Language Model API also supports two views physical and logical.</p>

<p>Each source file is represented via 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmFile.html">
CsmFile</a> interface. The 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmFile.html">
CsmFile</a> has a method that returns a collection of all declarations within this file - 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmFile.html#getDeclarations()">
getDeclarations()</a>. This is a <i>physical</i> view.</p>


<p><i>Logical</i> view is represented via 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">
CsmProject</a> and
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmNamespace.html">
CsmNamespace</a> interfaces. Each user project has correspondent instance of
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">
CsmProject</a> interface; each namespace is represented via
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmNamespace.html">
CsmNamespace</a> interface.

<p>For better understanding of how to go through the both hierarchies, 
you can look the source code of the 
<code><a href="http://www.netbeans.org/source/browse/cnd/modelapi/src/org/netbeans/modules/cnd/api/model/util/CsmTracer.java">
CsmTracer</a></code> class (<code>org.netbeans.modules.cnd.api.model.util.CsmTracer</code>). 
It was written for tracing and testing purposes. It dumps model. The
<code>dumpModel(CsmProject project)</code> method dumps the <i>logical</i> structure of the project 
passed as a parameter.

The
<code>dumpModel(CsmFile file)</code> method dumps the <i>physical</i> structure 
of the given file.
</p>

<h3>Instances lifecycle, UIDs and persistence</h3>

<p>The instances that implement the mentioned above interfaces has different lifecycles.
The most general rule is that they can not be considered as long living objects.
These objects can be garbage collected and, later on, replaced by the new instances.</p>

<p>The Language Model data is spacious. 
To not let it occupy too much memory, a <i>persistence</i> was introduced.
The  <i>persistence</i> is a mechanizm that allows to store instance data on a disk,
and to get it back on request. Each instance is associated with a special unique 
identifier , <i>UID</i>. Instead of storing a reference to the object itself,
its <i>UID</i> is stored. So instance can be garbage collected. Later on,
the instance can be gotten via this <i>UID</i>.</p>

<p>There is an in-memory cache for objects that uses LRU strategy. 
So, for recently used objects, getting by <i>UID</i> is just getting from a map.
In this case you get the same instance that you (or someone else) used recently.
If the object has been already garbage collected, new instance is read
from persistence.</p>

<p>Two key interfaces that are related with UIDs are 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmUID.html">
CsmUID</a> and
<a href="../org-netbeans-modules-cnd-api-model/index.html">
CsmIdentifiable</a>. The  UIDs are represented with instances of the
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmUID.html">
CsmUID</a> interface. It has the only method - 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmUID.html#getObject()">
getObject()</a>. The method returns the object that corresponds the UID.
</p>


<p>The <a href="../org-netbeans-modules-cnd-api-model/index.html">
CsmIdentifiable</a> 
interface represents an object that can has an UID associated,
and be restored from this UID later on. 
It also has the only method - 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmIdentifiable.html#getUID()">    
getUID()</a>. Each of the above mentioned interfaces that describe the program structure
is derived from <a href="../org-netbeans-modules-cnd-api-model/index.html">
CsmIdentifiable</a>.
</p>

<p>As you see, using UIDs is quite straightforward.
Just store UID instead of direct reference, 
and use <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmUID.html#getObject()">
getObject()</a> later on, when you need the correspondent instance.

<h3>Do not use instanceof</h3>

<p>A lot of Language Model API methods return a collection of declarations. 
For example
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmNamespace.html#getDeclarations()">    
CsmNamespace.getDeclarations()</a> returns a collection of all the declarations that belong to this namespace.
You often need to understand, what are these declarations - for each declaration you typically
are interested to know, whether it is a class, or a function, or a typedef, etc.
The first thing that comes to developer's mind is to check this via <code>instanceof</code> operator.
</p>

<p>However we strongly discourage you from using <code>instanceof</code>.
The reason is that sometimes an implementation class can inherit 
some iterface "occasionally" - just for some implementation-related
reason.</p>

<p>The best way is to use a <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/util/CsmKindUtilities.html">
CsmKindUtilities</a> class. It has a plenty of <code>is...()</code> methods: 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/util/CsmKindUtilities.html#isClass(org.netbeans.modules.cnd.api.model.CsmObject)">isClass()</a>, 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/util/CsmKindUtilities.html#isField(org.netbeans.modules.cnd.api.model.CsmObject)">isField()</a>, 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/util/CsmKindUtilities.html#isFunctionDefinition(org.netbeans.modules.cnd.api.model.CsmObject)">isFunctionDefinition()</a>
and so on.
</p>

<p>There also is an enum 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmDeclaration.Kind.html">
CsmDeclaration.Kind</a> and a method 
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmDeclaration.html#getKind()">
CsmDeclaration.getKind()</a> that were initially created for distingwishing different kind of objects.
But infortunately there are several drawbacks. The main drawback is that the method
returns a single kind, while the object can belong to seceral kinds at once. 
Consuder some class' method. Is it a fuction? Yes, it is. Is it a member? Yes, sure.
In the case it contains its body, it is also a function definition as well.
Which of the three kinds should be return then? This shows a design flaw
that isn't fixed yet. It will be definitely corrected by the moment of 
making this API public. For now just use <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/util/CsmKindUtilities.html">
CsmKindUtilities</a> class.
</p>
    

<h3>Events and Listeners</h3>

<p>Language model supports three kind of listeners -
<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelListener.html">CsmModelListener</a>
, <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelStateListener.html">CsmModelStateListener</a>
and <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProgressListener.html">CsmProgressListener</a>
. The <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModel.html">CsmModel</a>
class maintains the list of the listeners. For each of the three, it has
a pair of <code>add***Listener()</code> and <code>remove***Listener()</code>
methods.


<dl>
    <dt><a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelListener.html">CsmModelListener</a>
    <dd><p>This listener is notified about each change in the Language Model content.
    When some model elements are changed or removed, or added, the
    <a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelListener.html#modelChanged(org.netbeans.modules.cnd.api.model.CsmChangeEvent)">
	modelChanged()</a> method is called.</p>
	
        <p>It is also notified when a project is opened 
	(<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelListener.html#projectOpened(org.netbeans.modules.cnd.api.model.CsmProject)">projectOpened()</a> method)
        or closed
	(<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelListener.html#projectClosed(org.netbeans.modules.cnd.api.model.CsmProject)">projectClosed()</a> method).
	The instance of the 
	<a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProject.html">CsmProject</a>
	interface that represents the project is passed as a parameter
	to these methods.
    </p>
    
    <dt><a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmModelStateListener.html">CsmModelStateListener</a>
    <dd><p>The listener is notified when the Language Model state is changed 
    as a result of switching modules on and off.
    Sometimes clients register these listener and dismiss unnecessary resources when the model is going down.
    </p>
    
    <dt><a href="../org-netbeans-modules-cnd-api-model/org/netbeans/modules/cnd/api/model/CsmProgressListener.html">CsmProgressListener</a>
    <dd><p>This one allows you to track the process of parsing files.
    For example, Code Assistance uses this listener to show the "Parsing..." progress indicator</p>
</dl>
    
<h3>Some code examples</h3>

<p>We will not provide examples right here. Instead we give a few links.</p>

<p>There are some examples in
<a href="../howto-code-analyzer/howto-code-analyzer.html">
How to Write a Simple Code Analyzer Using NetBeans&trade; C/C++ Development Pack API    
</a> article. They mostly illustrate how to traverse Language Model trees.
It is simple and good for first aquaintance.</p>

<p>There is a comprehensive example of going through the Language Model hierarchies in the
<code><a href="http://www.netbeans.org/source/browse/cnd/modelapi/src/org/netbeans/modules/cnd/api/model/util/CsmTracer.java">
CsmTracer</a></code> class (<code>org.netbeans.modules.cnd.api.model.util.CsmTracer</code>). 

<p>The best examples can be found in the code of the end user features of the 
NetBeans&trade; C/C++ Pack itself. 
The most convenient web interface for browsing the sources is OpenGrok at
<a href="http://deadlock.netbeans.org/opengrok/xref/cnd">http://deadlock.netbeans.org/opengrok/xref/cnd</a>
The code can also be found at 
<a href="http://www.netbeans.org/source/browse/cnd">http://www.netbeans.org/source/browse/cnd</a>.
</p>
    
</body>
</html>

Project Features

About this Project

CND was started in November 2009, is owned by DimaZh, and has 197 members.
By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20160708.bf2ac18). © 2014, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo
 
 
Close
loading
Please Confirm
Close