Skip to content

Commit

Permalink
Stripped down to demonstrate a couple of issues
Browse files Browse the repository at this point in the history
  • Loading branch information
ndw committed Sep 21, 2024
1 parent de4711a commit ab4d604
Show file tree
Hide file tree
Showing 37 changed files with 67 additions and 1,306 deletions.
195 changes: 47 additions & 148 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,149 +1,48 @@
# xmldoclet
# xmldoclet - link-bug-report branch

This branch contains the doclet stripped down to demonstrate two (apparent)
issues in the Doclet API. It doesn’t build complete or useful documentation, it
builds just enough to demonstrate two problems.

To reproduce the issues:

1. Build the project
2. Run the unit test in `DocletTest`; this will build JavaDoc for the toy example in `sample`.
3. Examine the doclet output, by default in `xmldoclet/doclet.xml`.

There are two problems:

1. In the JavaDoc for `ItemProcessor`, the link target is incorrect:

```
<purpose>
<body xmlns="http://www.w3.org/1999/xhtml">This is a link to <a class="ref"
href="org.example.packagea.Item"
java-class="Item"
java-package="org.example.packagea"
java-signature="Item">Item</a>.</body>
</purpose>
```

The `Item` is defined in `packageb`, but I don’t see anywhere in the API that
exposes that information. Poking around in the debugger, I think the
information about what has been imported into `packagea` is known, but it
isn’t exposed.

2. The JavaDoc for variables doesn’t expose the initializing expression. See `hello`:

```
<field access="public"
static="true"
name="hello"
final="true"
value="Hello">
<type package="java.lang" name="String" fullname="java.lang.String"/>
</field>
```

The initializing expression is `H\u0065llo`. Again, with the debugger, that
appears to be in the private API but unaccessible. I would like it to be possible
for the documentation to reflect the actual initializing expression. This is particularly
useful when, for example, a string contains many non-Latin characters.

This is a Javadoc doclet that produces XML output. The goal is that
all of the data available in the Doclet API should be available in the
resulting XML.

It’s still a little rough around the edges, but it does use the modern
JavaDoc APIs and not the old, now deprecated ones that appear in
several other doclets for this purpose.

## Installing the doclet

You have two choices for installing xmldoclet. You can download a release
from the Github [releases](https://github.com/Saxonica/xmldoclet/releases) page,
or you can use the Saxonica Maven repository at `https://dev.saxonica.com/maven`.
The Maven artifact is:

```xml
<dependency>
<groupId>com.saxonica</groupId>
<artifactId>xmldoclet</artifactId>
<version>x.y.z</version>
</dependency>
```

Where `x.y.z` should be replaced by the appropriate version.

Make sure that the xmldoclet jar file is on the classpath used by the Javadoc
command.

## Running the doclet

The xmldoclet recognizes the following options:

<dl>
<div>
<dt><code>-d</code></dt>
<dd>The destination directory, if specified this is where the output file
will be stored. By default, this is <code>.</code>, the current directory.
</dd>
</div>
<div>
<dt><code>-outputfile</code></dt>
<dd>The name of the output file. By default, this is <code>doclet.xml</code>.
</dd>
</div>
<div>
<dt><code>-sourcepath</code></dt>
<dd>A list of directories where Java source files can be found. See <em>source paths</em>
below.
</dd>
</div>
<div>
<dt><code>-doctitle</code>, <code>-windowtitle</code>, <code>-notimestamp</code></dt>
<dd>These options are accepted, but ignored. This allows the doclet to be
used with build tools that send them without having to work out how to
suppress them.
</dd>
</div>
</dt>

### Source paths

The new Javadoc APIs don’t appear to expose any record of imported
classes. You can’t tell, for example, that `org.example.MyClass`
contains an `import java.util.Locale` statement. Inspecting the source
code for the standard doclet, reveals that this information is
accessed through a variety of private APIs (the information is *in*
the objects, but not exposed in any public APIs!).

Unfortunately, *without* access to the imports, it’s not possible to
tell what an unqualified type name refers to! What is _Locale
mylocale_? It could be `java.util.Local` or it could be
`org.example.otherpackage.Locale`.

The xmldoclet applies brute force. It relies on the `javaparser` APIs
and simply reads the sources itself. That’s why you have to specify a
source path. This can lead to spurious warnings from the Java parser,
but they aren’t relevant because the only thing xmldoclet uses the
parsed AST for is to extract the list of imports.

## XML output

The XML output is in the `https://saxonica.com/ns/doclet` namespace.
It conforms to the RELAX NG schema `doclet.rnc` in
`xmldoclet/src/main/resources/doclet.rnc`.

All of the comments and tags are in the HTML namespace, wrapped in a
`body` element. They are guaranteed to be well-formed, even if the
markup in the Java sources is not. This is achieved by parsing them
with the Validator.nu HTML 5 parser.

Notes:

* The HTML 5 parser doesn’t preserve comments. To work around this
limitation, any literal comments in the Javadoc source:

```xml
<!-- this is a comment. -->
```

are represented using an HTML extension element:
`xmldoclet-comment`. For example:

```xml
<xmldoclet-comment text=" this is a comment. "/>
```

* Some `char` constant values can’t be represented in XML. For
surrogate pairs and characters less than 0x20, the string
`(char) 0x…` is used for the value instead of the character’s
literal value.

## Feedback welcome

Much of the output is the result of experimentation and exploring the
Javadoc APIs. If you discover that xmldoclet produces output that
doesn’t conform to the schema, or if you think that the output is
incomplete or incorrect, please [open an issue](https://github.com/Saxonica/xmldoclet/issues).

## Change log

* **0.8.0** Fixed method names

Output the “simple” method name in the name attribute on method elements.
The full signature is also provided and the parameters and their types are available
from children.

* **0.7.0** Improved presentation of interfaces

Reworked the way interfaces are presented so that the methods inherited
from those interfaces (i.e., the methods not actually implemented on this class)
are shown.

* **0.6.0** Improved handling of method names and inheritance

Changed the “name” of methods to include the parameter types. (i.e., `foo(int)`
instead of `foo`). This allows them to be distinguished.

Fixed a bug where the methods inherited from interfaces were not shown.

Fixed a bug in computing visibility. Previously, the code looked for an explicit
~public~ or ~protected~ modifier. Now it *excludes* things explicitly marked ~private~.

Experimentally removed ~java.lang.Object~ as a supertype in the generated XML.

The previous version looked for methods and fields marked as public or protected, but that's not the same thing!

* **0.5.0** String constants now use “backslash-U” escapes for non-ASCII characters.
13 changes: 0 additions & 13 deletions sample/src/main/java/org/example/AbstractClass.java

This file was deleted.

23 changes: 0 additions & 23 deletions sample/src/main/java/org/example/AlternateImplementation.java

This file was deleted.

24 changes: 0 additions & 24 deletions sample/src/main/java/org/example/AnnoType.java

This file was deleted.

6 changes: 0 additions & 6 deletions sample/src/main/java/org/example/AxisIterator.java

This file was deleted.

17 changes: 0 additions & 17 deletions sample/src/main/java/org/example/EmptyIterator.java

This file was deleted.

4 changes: 0 additions & 4 deletions sample/src/main/java/org/example/Impl.java

This file was deleted.

8 changes: 0 additions & 8 deletions sample/src/main/java/org/example/ImplAB.java

This file was deleted.

13 changes: 0 additions & 13 deletions sample/src/main/java/org/example/ImplABC.java

This file was deleted.

27 changes: 0 additions & 27 deletions sample/src/main/java/org/example/Implementation.java

This file was deleted.

5 changes: 0 additions & 5 deletions sample/src/main/java/org/example/InterfaceA.java

This file was deleted.

5 changes: 0 additions & 5 deletions sample/src/main/java/org/example/InterfaceAB.java

This file was deleted.

5 changes: 0 additions & 5 deletions sample/src/main/java/org/example/InterfaceABC.java

This file was deleted.

17 changes: 0 additions & 17 deletions sample/src/main/java/org/example/IterImpl.java

This file was deleted.

5 changes: 0 additions & 5 deletions sample/src/main/java/org/example/Locale.java

This file was deleted.

13 changes: 13 additions & 0 deletions sample/src/main/java/org/example/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.example;

public class Main {
public final static String hello = "H\u0065llo";

/**
* The main entry point.
* @param args Command line arguments.
*/
public static void main(String[] args) {
System.out.println(hello);
}
}
Loading

0 comments on commit ab4d604

Please sign in to comment.