blob: 4183a2057d343be8f596f3210d82c58041781f46 [file] [log] [blame]
rymandd3eac92005-01-12 02:20:13 +00001<html>
4<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
5<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
6<meta name="ProgId" content="FrontPage.Editor.Document">
7<title>Design of a Tool for Checking API Usage in Eclipse-based Components</title>
12<h1>Design of a Tool for Checking API Usage in Eclipse-based Components</h1>
13<p>Jim des Rivieres<br>
rymane7a7d802005-01-18 07:53:38 +000014Last updated Jan 14, 2005</p>
rymandd3eac92005-01-12 02:20:13 +000015<p>This document contains the design for a tool for checking API usage in
16Eclipse-based components and products.</p>
18<p>For the purposes of this tool, a component is a set of plug-ins and plug-in
19fragments. Components must be disjoint, in that the plug-ins and fragments
20within one component must be distinct from those in other components. In other
21words, components partition the set of plug-ins and plug-in fragments into
22disjoint subsets. We also allow a form of library component containing&nbsp; no
23plug-ins or fragments; library components are used to describe class libraries
24such as J2SE that are not located inside any plug-in.</p>
25<p>The code for a component is the sum total of the code in the component's
26plug-ins and fragments (as described by the plug-in manifest). The code is in
27the form of Java types (predominantly classes and interfaces; J2SE 5.0 adds
28enumerations and annotation types). The types that are intended to be used by
29other components are called the component's API, and referred to as API types. A
30component can provide any number of API types, including none. Typically, only a
31subset of a component's types are part of its API. The rest are referred to as
32internal types. Non-public types are always considered internal.</p>
33<p>It's common to use Java packages to separate one component from another, and
34to separate API from internal within a component. Each component generally
35declares its code in packages different from those used by any other component.
36An API package is one that contains at least one API type. An internal package
37is one that contains no API types. The default assumption is that all public
38top-level types in an API package are API types.</p>
39<p>An API type declared in one component can be used by other components is
40various ways:</p>
42 <li>Declare a field, variable, parameter, or return type where the type is an
43 API type.</li>
44 <li>Cast the value on an expression to an API type.</li>
45 <li>Declare a class that implements an API interface.</li>
46 <li>Declare an interface that extends an API interface.</li>
47 <li>Declare a class that extends (subclasses) an API class.</li>
48 <li>Creates an instance of an API class.</li>
50<p>It is common for an API type to be intended to be used only in certain ways.
51In some cases, Java modifiers can be used to rule out unintended uses (e.g.,
52prevent subclassing by declaring the class &quot;final&quot;). But in many
53cases, the intended uses are spelled out in the type's specification (doc
54comment). The most common restrictions are:</p>
56 <li>Clients may not instantiate this API class.</li>
57 <li>Clients may not subclass this API class.</li>
58 <li>Clients may not implement this API interface. It follows that the client
59 may not extend the interface either.</li>
61<p>Types have members (fields, methods, types). For the present, we make the
62simplifying assumption that all public and protected members of an API type are
63intended to be used by other components.</p>
64<h2>Component description files</h2>
65<p>Each component will be described via a component description file. The file
rymane7a7d802005-01-18 07:53:38 +000066format is XML-based; the DTD follows (complete <a href="">XML
68<pre>&lt;!ELEMENT component (plugin* package* component-depends)&gt;
rymandd3eac92005-01-12 02:20:13 +000069&lt;!ATTLIST component
72The &lt;component&gt; element provides information about a component.
75 <li><b>name</b> - the component name; &quot;Eclipse Platform Generic
76 Workbench&quot;; note that this name is used to refer to the component and
77 distinguish it from other components (but otherwise has no official status
78 in Eclipse ontology)</li>
80<p>Child elements or the &lt;component&gt; element describe the set of plug-ins
rymane7a7d802005-01-18 07:53:38 +000081and fragments making up the component, provide information about the Java
82packages and types in the component's code, and include a list of other
83components on which this component may depend.</p>
84<p>Each &lt;plugin&gt; element must identify a distinct plug-in or fragment. The
85list of plug-ins must be complete; that is, a component contains a plug-in (or
86fragment) if and only if a &lt;plugin&gt; element occurs as a child of the
87&lt;component&gt; element.</p>
rymandd3eac92005-01-12 02:20:13 +000088<pre>&lt;!ELEMENT plugin EMPTY&gt;
89&lt;!ATTLIST plugin
91 fragment (&quot;true&quot; | &quot;false&quot;) &quot;false&quot;
93The &lt;plugin&gt; element identifies a plug-in or plug-in fragment that is part
94of the component. Attributes:
96 <li><b>id</b> - the plug-in id or plug-in fragment id; e.g., &quot;org.eclipse.core.resources&quot;;
97 note that in the case of a fragment, this is the id of fragment itself</li>
98 <li><b>fragment</b> - whether this is a plug-in fragment as opposed to a
99 plug-in (default: plug-in)</li>
101<p>Each &lt;plugin&gt; element must identify a distinct plug-in or fragment. The
102list of plug-ins must be complete; that is, a component contains a plug-in (or
103fragment) if and only if a &lt;plugin&gt; element occurs as a child of the
104&lt;component&gt; element.</p>
105<pre>&lt;!ELEMENT package (type*)&gt;
106&lt;!ATTLIST package
108 exclusive (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
109 api (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
111The &lt;package&gt; element provides information about a package as used by the
112component. Attributes:
114 <li><b>name</b> - Java package name; e.g., &quot;javax.swing&quot;, &quot;org.eclipse.ui&quot;</li>
115 <li><b>api</b> - whether top-level types in this package are API types by
rymane7a7d802005-01-18 07:53:38 +0000116 default (default: true). It's good practice for all public classes API
117 top-level types in a package to be considered API. Specify &quot;false&quot;
118 in order to explicitly list API types found in the package.</li>
rymandd3eac92005-01-12 02:20:13 +0000119 <li><b>exclusive</b> - whether this package is reserved for exclusive use by
120 this component (default: true); specify &quot;false&quot; in (rare) cases
121 where a multiple components declared types in the same package. Package
122 sharing is only by mutual consent; all components involved must explicitly
123 declare the package as exclusive=&quot;false&quot; (even if it has no API
124 types).</li>
126<p>Each &lt;package&gt; element must identify a distinct package relative to
127that component. If the unusual case where a package is shared with other
128components, the &lt;package&gt; element is understood to apply only to the types
129the component actually declares, and has no bearing on the types declared in the
130same package in any other component. The list of packages may be incomplete; if
131the component contains code in a package not mentioned in the list, the package
132is considered to be internal (equivalent to being explicitly described as
133&lt;package name=&quot;...&quot; api=&quot;false&quot; /&gt;). The children of
134the &lt;package&gt; element provide information about specific types in the
136<pre>&lt;!ELEMENT type EMPTY&gt;
137&lt;!ATTLIST type
139 reference (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
140 implement (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
141 subclass (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
142 instantiate (&quot;true&quot; | &quot;false&quot;) &quot;true&quot;
144The &lt;type&gt; element provides information about a top-level type in a
145package. Attributes:
147 <li><b>name</b> - simple name of a top-level Java class, interface,
148 enumeration, or annotation type; e.g., &quot;String&quot;, &quot;IResource&quot;</li>
149 <li><b>reference</b> - whether other components are expected to reference this
150 type by name (default: true); specify &quot;false&quot; to indicate that the
151 type is internal</li>
152 <li><b>implement</b> - whether other components are expected to declare a
153 class that implements this interface (default: true); specify
154 &quot;false&quot; for an interface that other components are not supposed to
155 implement directly; this attribute is ignored for classes, enumerations, and
156 annotation types, none of which can be meaningfully implemented</li>
157 <li><b>subclass</b> - whether other components are expected to declare a class
158 that directly subclasses this class (default: true); specify
159 &quot;false&quot; for a class that other components are not supposed to
160 subclass directly; this attribute is ignored for interfaces, enumerations,
161 and annotation types, none of which can be meaningfully subclassed</li>
162 <li><b>instantiate</b> - whether other components are expected to create
163 instances of this class or annotation type (default: true); specify
164 &quot;false&quot; for a type that other components are not supposed to
165 instantiate directly; this attribute is ignored for interfaces and
166 enumerations, neither of which can be meaningfully instantiated; this
167 attribute is moot for classes that are declared final (or ones with no
168 generally accessible constructors), since the Java compiler and JRE will
169 block outside attempts to instantiate</li>
171<p>(Note: We could extend the schema in the future to allow &lt;type&gt;
172elements to provide analogous information about their members. We could also
173extend the &lt;component&gt; element to allow aspects other than code API to be
rymane7a7d802005-01-18 07:53:38 +0000175<pre>&lt;!ELEMENT component-depends (component-ref*)&gt;
176&lt;!ATTLIST component-depends
177 unrestricted (&quot;true&quot; | &quot;false&quot;) &quot;false&quot;
179&lt;!ELEMENT component-ref EMPTY&gt;
180&lt;!ATTLIST component-ref
183The &lt;component-depends&gt; element identifies other components on which this
184component is allowed to depend. Attributes:
186 <li><b>unrestricted</b> - whether this component is allowed to depend on
187 arbitrary other components, or just the ones explicitly named by the
188 &lt;component-ref&gt; children</li>
190If a component specifies &lt;component-depends
191unrestricted=&quot;true&quot;&gt;, then it is allowed to depend on any component
192(and the children, if any, are ignored). Otherwise, the &lt;component-ref&gt;
193elements give the names of the component on which this component may depend. The
194&lt;component-ref&gt; element identifies a component by name. Attributes:
196 <li><b>name</b> - the name of the referenced component; e.g., &quot;Eclipse
197 Platform Generic Workbench&quot;</li>
rymandd3eac92005-01-12 02:20:13 +0000199<h3>Example</h3>
200<p>A component description of one of the Eclipse Platform components:</p>
201<pre>&lt;component name=&quot;Eclipse Platform Core Resources&quot;&gt;
202 &lt;plugin id=&quot;org.eclipse.core.resources&quot; /&gt;
203 &lt;plugin id=&quot;org.eclipse.core.resources.win32&quot; fragment=&quot;true&quot; /&gt;
204 &lt;plugin id=&quot;org.eclipse.core.resources.linux&quot; fragment=&quot;true&quot; /&gt;
205 &lt;plugin id=&quot;org.eclipse.core.resources.hpux&quot; fragment=&quot;true&quot; /&gt;
206 &lt;plugin id=&quot;org.eclipse.core.resources.macosx&quot; fragment=&quot;true&quot; /&gt;
207 &lt;plugin id=&quot;org.eclipse.core.resources.qnx&quot; fragment=&quot;true&quot; /&gt;
209 &lt;package name=&quot;org.eclipse.core.resources&quot;&gt;
210&nbsp;&nbsp; &lt;type name=&quot;ICommand&quot; implement=&quot;false&quot; /&gt;
211&nbsp;&nbsp; &lt;type name=&quot;IContainer&quot; implement=&quot;false&quot; /&gt;
212&nbsp;&nbsp; &lt;type name=&quot;IFile&quot; implement=&quot;false&quot; /&gt;
213&nbsp;&nbsp; &lt;type name=&quot;IFileState&quot; implement=&quot;false&quot; /&gt;
214&nbsp;&nbsp; &lt;type name=&quot;IFolder&quot; implement=&quot;false&quot; /&gt;
215&nbsp;&nbsp; &lt;type name=&quot;IMarker&quot; implement=&quot;false&quot; /&gt;
216&nbsp;&nbsp; &lt;type name=&quot;IMarkerDelta&quot; implement=&quot;false&quot; /&gt;
217&nbsp;&nbsp; &lt;type name=&quot;IPathVariableChangeEvent&quot; implement=&quot;false&quot; /&gt;
218&nbsp;&nbsp; &lt;type name=&quot;IPathVariableManager&quot; implement=&quot;false&quot; /&gt;
219&nbsp;&nbsp; &lt;type name=&quot;IProject&quot; implement=&quot;false&quot; /&gt;
220&nbsp;&nbsp; &lt;type name=&quot;IProjectDescription&quot; implement=&quot;false&quot; /&gt;
221&nbsp;&nbsp; &lt;type name=&quot;IProjectNatureDescriptor&quot; implement=&quot;false&quot; /&gt;
222&nbsp;&nbsp; &lt;type name=&quot;IResource&quot; implement=&quot;false&quot; /&gt;
223&nbsp;&nbsp; &lt;type name=&quot;IResourceChangeEvent&quot; implement=&quot;false&quot; /&gt;
224&nbsp;&nbsp; &lt;type name=&quot;IResourceDelta&quot; implement=&quot;false&quot; /&gt;
225&nbsp;&nbsp; &lt;type name=&quot;IResourceProxy&quot; implement=&quot;false&quot; /&gt;
226&nbsp;&nbsp; &lt;type name=&quot;IResourceRuleFactory&quot; implement=&quot;false&quot; /&gt;
227&nbsp;&nbsp; &lt;type name=&quot;IResourceStatus&quot; implement=&quot;false&quot; /&gt;
228&nbsp;&nbsp; &lt;type name=&quot;ISaveContext&quot; implement=&quot;false&quot; /&gt;
229&nbsp;&nbsp; &lt;type name=&quot;ISavedState&quot; implement=&quot;false&quot; /&gt;
230&nbsp;&nbsp; &lt;type name=&quot;ISynchronizer&quot; implement=&quot;false&quot; /&gt;
231&nbsp;&nbsp; &lt;type name=&quot;IWorkspace&quot; implement=&quot;false&quot; /&gt;
232&nbsp;&nbsp; &lt;type name=&quot;IWorkspaceDescription&quot; implement=&quot;false&quot; /&gt;
233&nbsp;&nbsp; &lt;type name=&quot;IWorkspaceRoot&quot; implement=&quot;false&quot; /&gt;
234&nbsp;&nbsp; &lt;type name=&quot;ResourcesPlugin&quot; subclass=&quot;false&quot; instantiate=&quot;false&quot; /&gt;
235 &lt;/package&gt;
236 &lt;package name=&quot;org.eclipse.core.resources.mapping&quot;&gt;
237 &lt;/package&gt;
238 &lt;package name=&quot;org.eclipse.core.resources.refresh&quot;&gt;
239&nbsp;&nbsp; &lt;type name=&quot;IRefreshResult&quot; implement=&quot;false&quot; /&gt;
240 &lt;/package&gt;
241 &lt;package name=&quot;;&gt;
242&nbsp;&nbsp; &lt;type name=&quot;IResourceTree&quot; implement=&quot;false&quot; /&gt;
243 &lt;/package&gt;
rymane7a7d802005-01-18 07:53:38 +0000244 &lt;component-depends&gt;
245 &lt;component-ref name=&quot;Eclipse Platform Core Resources&quot; /&gt;
246 &lt;component-ref name=&quot;J2SE&quot; /&gt;
247 &lt;/component-depends&gt;
rymandd3eac92005-01-12 02:20:13 +0000248&lt;/component&gt;</pre>
249<h2>How component descriptions are used</h2>
251 <li><b>Component package/type map</b> - Given the code for a component and its
252 component description, you can generate a fleshed-out list of the API types
253 declared by the component. (It's considerably harder to properly describe
254 the set of API members, since this involves building the supertype chain and
255 performing inheritance. Since the supertype chain need not be confined to a
256 single component, you also need the code for required plug-ins, etc.)</li>
257 <li><b>Inter-component reference map</b> - Given the code for a component, its
258 component description, and the component descriptions for all other
259 components to which the given component may contain references, you can
260 generate the list of external references from the component to types in some
261 other component (possibly unknown, possibly ambiguous). In particular, you
262 can do this without needing to consult the code for the other components (or
263 even needing the code to be available).</li>
264 <li><b>Fragile usage map</b> - You can go further and classify inter-component
265 usage as fragile. This requires the code for a component, its component
266 description, and the component descriptions for all other components to
267 which the given component may contain references. In the limited case of
268 shared packages between components, the code for these components may be
269 needed to disambiguate external references to types in the shared package. A
270 fragile external reference is any of:
271 <ul>
272 <li>A reference to an internal type in another (possibly unknown)
273 component.</li>
274 <li>A declaration of a subclass of a class C in another component where C
275 is described as subclass=&quot;false&quot;.</li>
276 <li>A declaration of a class implementing an interface I in another
277 component where I is described as implement=&quot;false&quot;.</li>
278 <li>An invocation of a constructor of a class C in another component where
279 C is described as instantiate=&quot;false&quot;.</li>
280 <li>A declaration of a type in a package P that another component
281 describes as exclusive=&quot;true&quot;.</li>
282 </ul>
283 </li>
rymane7a7d802005-01-18 07:53:38 +0000285<h2>Change history</h2>
287 <li>Dec. 23, 2004 - Initial version</li>
288 <li>Jan. 14, 2005
289 <ul>
290 <li>Added &lt;component-depends&gt; element to allow each component to
291 explicitly specify which other component it may depend on.</li>
292 <li>Added clarification to &quot;api&quot; attribute of &lt;package&gt;
293 element re: this is in line with good practice of making all top-types
294 public types in an API package being considered API.</li>
295 </ul>
296 </li>
rymandd3eac92005-01-12 02:20:13 +0000298