ndai | d0ec2ad | 2005-07-09 19:43:56 +0000 | [diff] [blame] | 1 | <html> |
| 2 | |
| 3 | <head> |
| 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> |
| 8 | </head> |
| 9 | |
| 10 | <body> |
| 11 | |
| 12 | <h1>Design of a Tool for Checking API Usage in Eclipse-based Components</h1> |
| 13 | <p>Jim des Rivieres<br> |
| 14 | Last updated Jan 14, 2005</p> |
| 15 | <p>This document contains the design for a tool for checking API usage in |
| 16 | Eclipse-based components and products.</p> |
| 17 | <h2>Components</h2> |
| 18 | <p>For the purposes of this tool, a component is a set of plug-ins and plug-in |
| 19 | fragments. Components must be disjoint, in that the plug-ins and fragments |
| 20 | within one component must be distinct from those in other components. In other |
| 21 | words, components partition the set of plug-ins and plug-in fragments into |
| 22 | disjoint subsets. We also allow a form of library component containing no |
| 23 | plug-ins or fragments; library components are used to describe class libraries |
| 24 | such 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 |
| 26 | plug-ins and fragments (as described by the plug-in manifest). The code is in |
| 27 | the form of Java types (predominantly classes and interfaces; J2SE 5.0 adds |
| 28 | enumerations and annotation types). The types that are intended to be used by |
| 29 | other components are called the component's API, and referred to as API types. A |
| 30 | component can provide any number of API types, including none. Typically, only a |
| 31 | subset of a component's types are part of its API. The rest are referred to as |
| 32 | internal 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 |
| 34 | to separate API from internal within a component. Each component generally |
| 35 | declares its code in packages different from those used by any other component. |
| 36 | An API package is one that contains at least one API type. An internal package |
| 37 | is one that contains no API types. The default assumption is that all public |
| 38 | top-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 |
| 40 | various ways:</p> |
| 41 | <ul> |
| 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> |
| 49 | </ul> |
| 50 | <p>It is common for an API type to be intended to be used only in certain ways. |
| 51 | In some cases, Java modifiers can be used to rule out unintended uses (e.g., |
| 52 | prevent subclassing by declaring the class "final"). But in many |
| 53 | cases, the intended uses are spelled out in the type's specification (doc |
| 54 | comment). The most common restrictions are:</p> |
| 55 | <ul> |
| 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> |
| 60 | </ul> |
| 61 | <p>Types have members (fields, methods, types). For the present, we make the |
| 62 | simplifying assumption that all public and protected members of an API type are |
| 63 | intended 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 |
| 66 | format is XML-based; the DTD follows (complete <a href="http://dev.eclipse.org/viewcvs/index.cgi/working/apitools/component.xsd?cvsroot=WebTools_Project">XML |
| 67 | scheme</a>):</p> |
| 68 | <pre><!ELEMENT component (plugin* package* component-depends)> |
| 69 | <!ATTLIST component |
| 70 | name CDATA #REQUIRED |
| 71 | ></pre> |
| 72 | The <component> element provides information about a component. |
| 73 | Attributes: |
| 74 | <ul> |
| 75 | <li><b>name</b> - the component name; "Eclipse Platform Generic |
| 76 | Workbench"; 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> |
| 79 | </ul> |
| 80 | <p>Child elements or the <component> element describe the set of plug-ins |
| 81 | and fragments making up the component, provide information about the Java |
| 82 | packages and types in the component's code, and include a list of other |
| 83 | components on which this component may depend.</p> |
| 84 | <p>Each <plugin> element must identify a distinct plug-in or fragment. The |
| 85 | list of plug-ins must be complete; that is, a component contains a plug-in (or |
| 86 | fragment) if and only if a <plugin> element occurs as a child of the |
| 87 | <component> element.</p> |
| 88 | <pre><!ELEMENT plugin EMPTY> |
| 89 | <!ATTLIST plugin |
| 90 | id CDATA #REQUIRED |
| 91 | fragment ("true" | "false") "false" |
| 92 | ></pre> |
| 93 | The <plugin> element identifies a plug-in or plug-in fragment that is part |
| 94 | of the component. Attributes: |
| 95 | <ul> |
| 96 | <li><b>id</b> - the plug-in id or plug-in fragment id; e.g., "org.eclipse.core.resources"; |
| 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> |
| 100 | </ul> |
| 101 | <p>Each <plugin> element must identify a distinct plug-in or fragment. The |
| 102 | list of plug-ins must be complete; that is, a component contains a plug-in (or |
| 103 | fragment) if and only if a <plugin> element occurs as a child of the |
| 104 | <component> element.</p> |
| 105 | <pre><!ELEMENT package (type*)> |
| 106 | <!ATTLIST package |
| 107 | name CDATA #REQUIRED |
| 108 | exclusive ("true" | "false") "true" |
| 109 | api ("true" | "false") "true" |
| 110 | ></pre> |
| 111 | The <package> element provides information about a package as used by the |
| 112 | component. Attributes: |
| 113 | <ul> |
| 114 | <li><b>name</b> - Java package name; e.g., "javax.swing", "org.eclipse.ui"</li> |
| 115 | <li><b>api</b> - whether top-level types in this package are API types by |
| 116 | default (default: true). It's good practice for all public classes API |
| 117 | top-level types in a package to be considered API. Specify "false" |
| 118 | in order to explicitly list API types found in the package.</li> |
| 119 | <li><b>exclusive</b> - whether this package is reserved for exclusive use by |
| 120 | this component (default: true); specify "false" 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="false" (even if it has no API |
| 124 | types).</li> |
| 125 | </ul> |
| 126 | <p>Each <package> element must identify a distinct package relative to |
| 127 | that component. If the unusual case where a package is shared with other |
| 128 | components, the <package> element is understood to apply only to the types |
| 129 | the component actually declares, and has no bearing on the types declared in the |
| 130 | same package in any other component. The list of packages may be incomplete; if |
| 131 | the component contains code in a package not mentioned in the list, the package |
| 132 | is considered to be internal (equivalent to being explicitly described as |
| 133 | <package name="..." api="false" />). The children of |
| 134 | the <package> element provide information about specific types in the |
| 135 | package.</p> |
| 136 | <pre><!ELEMENT type EMPTY> |
| 137 | <!ATTLIST type |
| 138 | name CDATA #REQUIRED |
| 139 | reference ("true" | "false") "true" |
| 140 | implement ("true" | "false") "true" |
| 141 | subclass ("true" | "false") "true" |
| 142 | instantiate ("true" | "false") "true" |
| 143 | ></pre> |
| 144 | The <type> element provides information about a top-level type in a |
| 145 | package. Attributes: |
| 146 | <ul> |
| 147 | <li><b>name</b> - simple name of a top-level Java class, interface, |
| 148 | enumeration, or annotation type; e.g., "String", "IResource"</li> |
| 149 | <li><b>reference</b> - whether other components are expected to reference this |
| 150 | type by name (default: true); specify "false" 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 | "false" 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 | "false" 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 | "false" 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> |
| 170 | </ul> |
| 171 | <p>(Note: We could extend the schema in the future to allow <type> |
| 172 | elements to provide analogous information about their members. We could also |
| 173 | extend the <component> element to allow aspects other than code API to be |
| 174 | described.)</p> |
| 175 | <pre><!ELEMENT component-depends (component-ref*)> |
| 176 | <!ATTLIST component-depends |
| 177 | unrestricted ("true" | "false") "false" |
| 178 | > |
| 179 | <!ELEMENT component-ref EMPTY> |
| 180 | <!ATTLIST component-ref |
| 181 | name CDATA #REQUIRED |
| 182 | ></pre> |
| 183 | The <component-depends> element identifies other components on which this |
| 184 | component is allowed to depend. Attributes: |
| 185 | <ul> |
| 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 | <component-ref> children</li> |
| 189 | </ul> |
| 190 | If a component specifies <component-depends |
| 191 | unrestricted="true">, then it is allowed to depend on any component |
| 192 | (and the children, if any, are ignored). Otherwise, the <component-ref> |
| 193 | elements give the names of the component on which this component may depend. The |
| 194 | <component-ref> element identifies a component by name. Attributes: |
| 195 | <ul> |
| 196 | <li><b>name</b> - the name of the referenced component; e.g., "Eclipse |
| 197 | Platform Generic Workbench"</li> |
| 198 | </ul> |
| 199 | <h3>Example</h3> |
| 200 | <p>A component description of one of the Eclipse Platform components:</p> |
| 201 | <pre><component name="Eclipse Platform Core Resources"> |
| 202 | <plugin id="org.eclipse.core.resources" /> |
| 203 | <plugin id="org.eclipse.core.resources.win32" fragment="true" /> |
| 204 | <plugin id="org.eclipse.core.resources.linux" fragment="true" /> |
| 205 | <plugin id="org.eclipse.core.resources.hpux" fragment="true" /> |
| 206 | <plugin id="org.eclipse.core.resources.macosx" fragment="true" /> |
| 207 | <plugin id="org.eclipse.core.resources.qnx" fragment="true" /> |
| 208 | |
| 209 | <package name="org.eclipse.core.resources"> |
| 210 | <type name="ICommand" implement="false" /> |
| 211 | <type name="IContainer" implement="false" /> |
| 212 | <type name="IFile" implement="false" /> |
| 213 | <type name="IFileState" implement="false" /> |
| 214 | <type name="IFolder" implement="false" /> |
| 215 | <type name="IMarker" implement="false" /> |
| 216 | <type name="IMarkerDelta" implement="false" /> |
| 217 | <type name="IPathVariableChangeEvent" implement="false" /> |
| 218 | <type name="IPathVariableManager" implement="false" /> |
| 219 | <type name="IProject" implement="false" /> |
| 220 | <type name="IProjectDescription" implement="false" /> |
| 221 | <type name="IProjectNatureDescriptor" implement="false" /> |
| 222 | <type name="IResource" implement="false" /> |
| 223 | <type name="IResourceChangeEvent" implement="false" /> |
| 224 | <type name="IResourceDelta" implement="false" /> |
| 225 | <type name="IResourceProxy" implement="false" /> |
| 226 | <type name="IResourceRuleFactory" implement="false" /> |
| 227 | <type name="IResourceStatus" implement="false" /> |
| 228 | <type name="ISaveContext" implement="false" /> |
| 229 | <type name="ISavedState" implement="false" /> |
| 230 | <type name="ISynchronizer" implement="false" /> |
| 231 | <type name="IWorkspace" implement="false" /> |
| 232 | <type name="IWorkspaceDescription" implement="false" /> |
| 233 | <type name="IWorkspaceRoot" implement="false" /> |
| 234 | <type name="ResourcesPlugin" subclass="false" instantiate="false" /> |
| 235 | </package> |
| 236 | <package name="org.eclipse.core.resources.mapping"> |
| 237 | </package> |
| 238 | <package name="org.eclipse.core.resources.refresh"> |
| 239 | <type name="IRefreshResult" implement="false" /> |
| 240 | </package> |
| 241 | <package name="org.eclipse.core.resources.team"> |
| 242 | <type name="IResourceTree" implement="false" /> |
| 243 | </package> |
| 244 | <component-depends> |
| 245 | <component-ref name="Eclipse Platform Core Resources" /> |
| 246 | <component-ref name="J2SE" /> |
| 247 | </component-depends> |
| 248 | </component></pre> |
| 249 | <h2>How component descriptions are used</h2> |
| 250 | <ul> |
| 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="false".</li> |
| 276 | <li>A declaration of a class implementing an interface I in another |
| 277 | component where I is described as implement="false".</li> |
| 278 | <li>An invocation of a constructor of a class C in another component where |
| 279 | C is described as instantiate="false".</li> |
| 280 | <li>A declaration of a type in a package P that another component |
| 281 | describes as exclusive="true".</li> |
| 282 | </ul> |
| 283 | </li> |
| 284 | </ul> |
| 285 | <h2>Change history</h2> |
| 286 | <ul> |
| 287 | <li>Dec. 23, 2004 - Initial version</li> |
| 288 | <li>Jan. 14, 2005 |
| 289 | <ul> |
| 290 | <li>Added <component-depends> element to allow each component to |
| 291 | explicitly specify which other component it may depend on.</li> |
| 292 | <li>Added clarification to "api" attribute of <package> |
| 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> |
| 297 | </ul> |
| 298 | |
| 299 | </body> |
| 300 | |
| 301 | </html> |