| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"> |
| <html> |
| |
| <head> |
| |
| <title>Design of a Tool for Checking API Usage in Eclipse-based |
| Components</title> |
| <link |
| rel="stylesheet" |
| type="text/css" |
| href="sources/formate.css"> |
| |
| </head> |
| |
| <body> |
| |
| <p class="ueberschrift">Design of a Tool for Checking API Usage in |
| Eclipse-based Components</p> |
| <p>Jim des Rivieres<br> |
| Last updated Jan 14, 2005</p> |
| |
| <p>This document contains the design for a tool for checking API usage |
| in Eclipse-based components and products.</p> |
| <p class="ueberschrift">Components</p> |
| <p>For the purposes of this tool, a component is a set of plug-ins and |
| plug-in fragments. Components must be disjoint, in that the plug-ins and |
| fragments within one component must be distinct from those in other |
| components. In other words, components partition the set of plug-ins and |
| plug-in fragments into disjoint subsets. We also allow a form of library |
| component containing no plug-ins or fragments; library components |
| are used to describe class libraries such as J2SE that are not located |
| inside any plug-in.</p> |
| <p>The code for a component is the sum total of the code in the |
| component's plug-ins and fragments (as described by the plug-in |
| manifest). The code is in the form of Java types (predominantly classes |
| and interfaces; J2SE 5.0 adds enumerations and annotation types). The |
| types that are intended to be used by other components are called the |
| component's API, and referred to as API types. A component can provide |
| any number of API types, including none. Typically, only a subset of a |
| component's types are part of its API. The rest are referred to as |
| internal types. Non-public types are always considered internal.</p> |
| <p>It's common to use Java packages to separate one component from |
| another, and to separate API from internal within a component. Each |
| component generally declares its code in packages different from those |
| used by any other component. An API package is one that contains at |
| least one API type. An internal package is one that contains no API |
| types. The default assumption is that all public top-level types in an |
| API package are API types.</p> |
| <p>An API type declared in one component can be used by other components |
| is various ways:</p> |
| <ul> |
| <li>Declare a field, variable, parameter, or return type where the |
| type is an API type.</li> |
| |
| <li>Cast the value on an expression to an API type.</li> |
| <li>Declare a class that implements an API interface.</li> |
| <li>Declare an interface that extends an API interface.</li> |
| <li>Declare a class that extends (subclasses) an API class.</li> |
| <li>Creates an instance of an API class.</li> |
| </ul> |
| |
| <p>It is common for an API type to be intended to be used only in |
| certain ways. In some cases, Java modifiers can be used to rule out |
| unintended uses (e.g., prevent subclassing by declaring the class |
| "final"). But in many cases, the intended uses are spelled out |
| in the type's specification (doc comment). The most common restrictions |
| are:</p> |
| <ul> |
| <li>Clients may not instantiate this API class.</li> |
| <li>Clients may not subclass this API class.</li> |
| <li>Clients may not implement this API interface. It follows that the |
| client may not extend the interface either.</li> |
| </ul> |
| <p>Types have members (fields, methods, types). For the present, we make |
| the simplifying assumption that all public and protected members of an |
| API type are intended to be used by other components.</p> |
| |
| <p class="ueberschrift">Component description files</p> |
| <p>Each component will be described via a component description file. |
| The file format is XML-based; the DTD follows:</p> |
| <pre><!ELEMENT component (plugin* package* component-depends)> |
| <!ATTLIST component |
| name CDATA #REQUIRED |
| ></pre> |
| The <component> element provides information about a component. |
| Attributes: |
| <ul> |
| <li><b>name</b> - the component name; "Eclipse Platform Generic |
| Workbench"; note that this name is used to refer to the component |
| and distinguish it from other components (but otherwise has no |
| official status in Eclipse ontology)</li> |
| |
| </ul> |
| <p>Child elements or the <component> element describe the set of |
| plug-ins and fragments making up the component, provide information |
| about the Java packages and types in the component's code, and include a |
| list of other components on which this component may depend.</p> |
| <p>Each <plugin> element must identify a distinct plug-in or |
| fragment. The list of plug-ins must be complete; that is, a component |
| contains a plug-in (or fragment) if and only if a <plugin> element |
| occurs as a child of the <component> element.</p> |
| |
| <pre><!ELEMENT plugin EMPTY> |
| <!ATTLIST plugin |
| id CDATA #REQUIRED |
| fragment ("true" | "false") "false" |
| ></pre> |
| The <plugin> element identifies a plug-in or plug-in fragment that |
| is part of the component. Attributes: |
| <ul> |
| <li><b>id</b> - the plug-in id or plug-in fragment id; e.g., |
| "org.eclipse.core.resources"; note that in the case of a |
| fragment, this is the id of fragment itself</li> |
| |
| <li><b>fragment</b> - whether this is a plug-in fragment as opposed to |
| a plug-in (default: plug-in)</li> |
| </ul> |
| <p>Each <plugin> element must identify a distinct plug-in or |
| fragment. The list of plug-ins must be complete; that is, a component |
| contains a plug-in (or fragment) if and only if a <plugin> element |
| occurs as a child of the <component> element.</p> |
| |
| <pre><!ELEMENT package (type*)> |
| <!ATTLIST package |
| name CDATA #REQUIRED |
| exclusive ("true" | "false") "true" |
| api ("true" | "false") "true" |
| |
| ></pre> |
| The <package> element provides information about a package as used |
| by the component. Attributes: |
| <ul> |
| <li><b>name</b> - Java package name; e.g., "javax.swing", |
| "org.eclipse.ui"</li> |
| <li><b>api</b> - whether top-level types in this package are API types |
| by default (default: true). It's good practice for all public classes |
| API top-level types in a package to be considered API. Specify |
| "false" in order to explicitly list API types found in the |
| package.</li> |
| <li><b>exclusive</b> - whether this package is reserved for exclusive |
| use by this component (default: true); specify "false" in |
| (rare) cases where a multiple components declared types in the same |
| package. Package sharing is only by mutual consent; all components |
| involved must explicitly declare the package as |
| exclusive="false" (even if it has no API types).</li> |
| </ul> |
| <p>Each <package> element must identify a distinct package |
| relative to that component. If the unusual case where a package is |
| shared with other components, the <package> element is understood |
| to apply only to the types the component actually declares, and has no |
| bearing on the types declared in the same package in any other |
| component. The list of packages may be incomplete; if the component |
| contains code in a package not mentioned in the list, the package is |
| considered to be internal (equivalent to being explicitly described as |
| |
| <package name="..." api="false" />). The |
| children of the <package> element provide information about |
| specific types in the package.</p> |
| <pre><!ELEMENT type EMPTY> |
| <!ATTLIST type |
| name CDATA #REQUIRED |
| reference ("true" | "false") "true" |
| |
| implement ("true" | "false") "true" |
| subclass ("true" | "false") "true" |
| |
| instantiate ("true" | "false") "true" |
| ></pre> |
| The <type> element provides information about a top-level type in |
| a package. Attributes: |
| <ul> |
| <li><b>name</b> - simple name of a top-level Java class, interface, |
| enumeration, or annotation type; e.g., "String", |
| "IResource"</li> |
| |
| <li><b>reference</b> - whether other components are expected to |
| reference this type by name (default: true); specify "false" |
| to indicate that the type is internal</li> |
| <li><b>implement</b> - whether other components are expected to |
| declare a class that implements this interface (default: true); |
| specify "false" for an interface that other components are |
| not supposed to implement directly; this attribute is ignored for |
| classes, enumerations, and annotation types, none of which can be |
| meaningfully implemented</li> |
| <li><b>subclass</b> - whether other components are expected to declare |
| a class that directly subclasses this class (default: true); specify |
| "false" for a class that other components are not supposed |
| to subclass directly; this attribute is ignored for interfaces, |
| enumerations, and annotation types, none of which can be meaningfully |
| subclassed</li> |
| |
| <li><b>instantiate</b> - whether other components are expected to |
| create instances of this class or annotation type (default: true); |
| specify "false" for a type that other components are not |
| supposed to instantiate directly; this attribute is ignored for |
| interfaces and enumerations, neither of which can be meaningfully |
| instantiated; this attribute is moot for classes that are declared |
| final (or ones with no generally accessible constructors), since the |
| Java compiler and JRE will block outside attempts to instantiate</li> |
| </ul> |
| <p>(Note: We could extend the schema in the future to allow <type> |
| elements to provide analogous information about their members. We could |
| also extend the <component> element to allow aspects other than |
| code API to be described.)</p> |
| |
| <pre><!ELEMENT component-depends (component-ref*)> |
| <!ATTLIST component-depends |
| unrestricted ("true" | "false") "false" |
| > |
| <!ELEMENT component-ref EMPTY> |
| <!ATTLIST component-ref |
| name CDATA #REQUIRED |
| ></pre> |
| The <component-depends> element identifies other components on |
| which this component is allowed to depend. Attributes: |
| |
| <ul> |
| <li><b>unrestricted</b> - whether this component is allowed to depend |
| on arbitrary other components, or just the ones explicitly named by |
| the <component-ref> children</li> |
| </ul> |
| If a component specifies <component-depends |
| unrestricted="true">, then it is allowed to depend on any |
| component (and the children, if any, are ignored). Otherwise, the |
| <component-ref> elements give the names of the component on which |
| this component may depend. The <component-ref> element identifies |
| a component by name. Attributes: |
| <ul> |
| <li><b>name</b> - the name of the referenced component; e.g., |
| "Eclipse Platform Generic Workbench"</li> |
| </ul> |
| <p class="ueberschrift">Example</p> |
| <p>A component description of one of the Eclipse Platform components:</p> |
| <pre> |
| <component name="Eclipse Platform Core Resources"> |
| |
| <plugin id="org.eclipse.core.resources" /> |
| <plugin id="org.eclipse.core.resources.win32" fragment="true" /> |
| <plugin id="org.eclipse.core.resources.linux" fragment="true" /> |
| |
| <plugin id="org.eclipse.core.resources.hpux" fragment="true" /> |
| <plugin id="org.eclipse.core.resources.macosx" fragment="true" /> |
| |
| <plugin id="org.eclipse.core.resources.qnx" fragment="true" /> |
| |
| <package name="org.eclipse.core.resources"> |
| <type name="ICommand" implement="false" /> |
| |
| <type name="IContainer" implement="false" /> |
| <type name="IFile" implement="false" /> |
| |
| <type name="IFileState" implement="false" /> |
| <type name="IFolder" implement="false" /> |
| |
| <type name="IMarker" implement="false" /> |
| <type name="IMarkerDelta" implement="false" /> |
| |
| <type name="IPathVariableChangeEvent" implement="false" /> |
| <type name="IPathVariableManager" implement="false" /> |
| |
| <type name="IProject" implement="false" /> |
| <type name="IProjectDescription" implement="false" /> |
| |
| <type name="IProjectNatureDescriptor" implement="false" /> |
| <type name="IResource" implement="false" /> |
| |
| <type name="IResourceChangeEvent" implement="false" /> |
| <type name="IResourceDelta" implement="false" /> |
| |
| <type name="IResourceProxy" implement="false" /> |
| <type name="IResourceRuleFactory" implement="false" /> |
| |
| <type name="IResourceStatus" implement="false" /> |
| <type name="ISaveContext" implement="false" /> |
| |
| <type name="ISavedState" implement="false" /> |
| <type name="ISynchronizer" implement="false" /> |
| |
| <type name="IWorkspace" implement="false" /> |
| <type name="IWorkspaceDescription" implement="false" /> |
| |
| <type name="IWorkspaceRoot" implement="false" /> |
| <type name="ResourcesPlugin" subclass="false" instantiate="false" /> |
| |
| </package> |
| <package name="org.eclipse.core.resources.mapping"> |
| </package> |
| <package name="org.eclipse.core.resources.refresh"> |
| <type name="IRefreshResult" implement="false" /> |
| |
| </package> |
| <package name="org.eclipse.core.resources.team"> |
| <type name="IResourceTree" implement="false" /> |
| </package> |
| |
| <component-depends> |
| <component-ref name="Eclipse Platform Core Resources" /> |
| <component-ref name="J2SE" /> |
| </component-depends> |
| |
| </component> |
| </pre> |
| <p class="ueberschrift">How component descriptions are used</p> |
| <ul> |
| <li><b>Component package/type map</b> - Given the code for a component |
| and its component description, you can generate a fleshed-out list of |
| the API types declared by the component. (It's considerably harder to |
| properly describe the set of API members, since this involves building |
| the supertype chain and performing inheritance. Since the supertype |
| chain need not be confined to a single component, you also need the |
| code for required plug-ins, etc.)</li> |
| <li><b>Inter-component reference map</b> - Given the code for a |
| component, its component description, and the component descriptions |
| for all other components to which the given component may contain |
| references, you can generate the list of external references from the |
| component to types in some other component (possibly unknown, possibly |
| ambiguous). In particular, you can do this without needing to consult |
| the code for the other components (or even needing the code to be |
| available).</li> |
| <li><b>Fragile usage map</b> - You can go further and classify |
| inter-component usage as fragile. This requires the code for a |
| component, its component description, and the component descriptions |
| for all other components to which the given component may contain |
| references. In the limited case of shared packages between components, |
| the code for these components may be needed to disambiguate external |
| references to types in the shared package. A fragile external |
| reference is any of: |
| <ul> |
| |
| <li>A reference to an internal type in another (possibly unknown) |
| component.</li> |
| <li>A declaration of a subclass of a class C in another component |
| where C is described as subclass="false".</li> |
| <li>A declaration of a class implementing an interface I in another |
| component where I is described as implement="false".</li> |
| <li>An invocation of a constructor of a class C in another component |
| where C is described as instantiate="false".</li> |
| |
| <li>A declaration of a type in a package P that another component |
| describes as exclusive="true".</li> |
| </ul> |
| </li> |
| </ul> |
| <p class="ueberschrift">Change history</p> |
| <ul> |
| <li>Dec. 23, 2004 - Initial version</li> |
| <li>Jan. 14, 2005 |
| <ul> |
| |
| <li>Added <component-depends> element to allow each component |
| to explicitly specify which other component it may depend on.</li> |
| <li>Added clarification to "api" attribute of |
| <package> element re: this is in line with good practice of |
| making all top-types public types in an API package being considered |
| API.</li> |
| </ul> |
| |
| </li> |
| </ul> |
| |
| |
| </body> |
| |
| </html> |