Commit 2cab2ce1 authored by Evan W. Patton's avatar Evan W. Patton Committed by Jeffrey Schiller

Use Javadocs for reference documentation descriptions

Change-Id: Icdd373c2090864129a3fba150529a035bd3519d3
parent 050ea9a3
......@@ -37,6 +37,10 @@
<ant inheritAll="false" useNativeBasedir="true" dir="buildserver" target="BuildServer"/>
</target>
<target name="docs">
<ant inheritAll="false" useNativeBasedir="true" dir="appengine" target="CopyToBuildWar"/>
</target>
<target name="extensions">
<ant inheritAll="false" useNativeBasedir="true" dir="components" target="clean"/>
<ant inheritAll="false" useNativeBasedir="true" dir="components" target="extensions"/>
......
......@@ -30,7 +30,6 @@ public class MarkdownDocumentationGenerator extends ComponentProcessor {
categoryDocs.put(component.getCategoryString(), new StringBuilder());
}
if (!sortedComponents.containsKey(component.getCategoryString())) {
//noinspection Convert2Diamond
sortedComponents.put(component.getCategoryString(), new TreeMap<String, ComponentInfo>());
}
categoryNames.put(component.getCategoryString(), component.getCategory());
......@@ -59,34 +58,45 @@ public class MarkdownDocumentationGenerator extends ComponentProcessor {
String name = entry.getKey();
out.write("\n\n## ");
out.write(name);
out.write(" {#" + name + "}");
out.write(" {#" + name + "}\n\n");
ComponentInfo info = entry.getValue();
out.write(info.getLongDescription(info));
out.write("\n\n");
outputProperties(name, info, out);
outputEvents(name, info, out);
outputMethods(name, info, out);
}
out.write("\n");
}
}
}
private void outputProperties(String name, ComponentInfo info, Writer out) throws IOException {
if (info.properties.size() == 0) {
return;
}
out.write(String.format("%n%n### Properties {#%s-Properties}%n%n{:.properties}", name));
boolean didOutput = false;
for (Property property : info.properties.values()) {
if (propertyIsHidden(info, property)) {
if (isPropertyHidden(info, property)) {
continue;
}
out.write(String.format("%n%n{:id=\"%s.%s\" %s} *%s*%n: ", name, property.name,
getPropertyClass(info, property), property.name));
out.write(property.getDescription());
out.write(property.getLongDescription(info));
didOutput = true;
}
if (!didOutput) {
out.write("\nNone\n");
}
}
private boolean propertyIsHidden(ComponentInfo info, Property property) {
return (!property.isUserVisible() && !info.designerProperties.containsKey(property.name))
|| (info.displayName.equals("Screen") && property.name.equals("ActionBar"));
private boolean isPropertyHidden(ComponentInfo info, Property property) {
return (isFeatureHidden(info, property) && !info.designerProperties.containsKey(property.name))
|| (info.displayName.equals("Screen") && property.name.equals("ActionBar"))
|| (info.displayName.equals("FirebaseDB") && property.name.equals("DefaultURL"))
|| (info.displayName.equals("CloudDB") && property.name.equals("DefaultRedisServer"));
}
private boolean isFeatureHidden(ComponentInfo info, Feature feature) {
return !feature.isUserVisible() || feature.isDeprecated();
}
private String getPropertyClass(ComponentInfo info, Property property) {
......@@ -107,27 +117,27 @@ public class MarkdownDocumentationGenerator extends ComponentProcessor {
}
private void outputEvents(String name, ComponentInfo info, Writer out) throws IOException {
if (info.events.size() == 0) {
return;
}
out.write(String.format("%n%n### Events {#%s-Events}%n%n{:.events}", name));
boolean didOutput = false;
for (Event event : info.events.values()) {
if (!event.userVisible) {
if (isFeatureHidden(info, event)) {
continue;
}
out.write(String.format("%n%n{:id=\"%s.%s\"} %s(%s)%n: ", name, event.name, event.name,
formatParameters(event.parameters)));
out.write(event.description);
out.write(event.getLongDescription(info));
didOutput = true;
}
if (!didOutput) {
out.write("\nNone\n");
}
}
private void outputMethods(String name, ComponentInfo info, Writer out) throws IOException {
if (info.methods.size() == 0) {
return;
}
out.write(String.format("%n%n### Methods {#%s-Methods}%n%n{:.methods}", name));
boolean didOutput = false;
for (Method method : info.methods.values()) {
if (!method.userVisible) {
if (isFeatureHidden(info, method)) {
continue;
}
String returnType = "";
......@@ -137,7 +147,11 @@ public class MarkdownDocumentationGenerator extends ComponentProcessor {
}
out.write(String.format("%n%n{:id=\"%s.%s\" class=\"method%s\"} <i/> %s(%s)%n: ", name,
method.name, returnType, method.name, formatParameters(method.parameters)));
out.write(method.description);
out.write(method.getLongDescription(info));
didOutput = true;
}
if (!didOutput) {
out.write("\nNone\n");
}
}
......
# Component Documentation in MIT App Inventor
## Reference Documentation
Long descriptions for the reference documentation are provided via Javadoc style comments. These comments can use Markdown formatting, `{@code ...}`, and `{@link #...}` to annotate content. Markdown formatting will be passed through to Jekyll for rendering when the documentation is built.
**Rule 1.** An empty Javadoc is ignored.
**Rule 2.** `{@code ...}` annotations in the Javadoc will be translated into Markdown inline code in single backticks.
**Rule 3.** `{@link #...}` can only be used to link within a given component. If you need to link across components, use the Markdown link format `[text]([category page]#Component.Block)`, for example `[Click](#Button.Click)` if linking to the Button Click event from within another User Interface component or `[Click](userinterface.html#Button.Click)` if linking from a component in another category.
**Rule 4.** The Javadoc content is only evaluated up to the first `@` character not escaped by a `\`.
**Rule 5.** If you want to include multiple paragraphs in the comment for a Property, Method, or Event, you will need to indent all but the first paragraph with 2 spaces, for example:
```java
/**
* This method does a thing.
*
* Note: Something important happens when this occurs,
* but it's mostly an implementation detail that you might
* be interested in.
*
* Learn more [here](http://example.com).
*/
```
**Rule 6.** If you want to suppress a Javadoc entirely from the user-facing documentation, include `@suppressdoc` anywhere in the Javadoc string.
**Rule 7.** If you want to suppress only a portion of the Javadoc, you can specify `@internaldoc` at the beginning of the non-public content. Only the content from the beginning of the comment to the `@internaldoc` will be put into the Markdown documentation.
## Tooltips
Tooltips for blocks are provided via the `description` field on the `@Simple*` annotations. If you have both getter and setters for a property in a component, you must put the `description` on the first element as it appears.
Tooltips are populated using the following algorithm:
1. When an annotated element is first encountered, the `description` field is first populated with the Javadoc as described in the previous section.
2. If the annotation specifies a description, it will overwrite the Javadoc version.
*NB: This only happens with the Javadoc and annotation on the same element. If you specify multiple annotationed elements (e.g., property getter and setter), this rule is only evaluated one for the property name. This can be combined with Tip 1 above.*
3. If both the Javadoc and description are empty, then a default description will be generated in the form of the string "%1 for %2" where %1 is the element type (e.g., "Property") and %2 is the element name (e.g., "Enabled").
4. If another element of the same name is annotated and contains a non-empty description, replace the existing description with the new description if either of these conditions is true:
1. The previously encountered description is empty, or
2. The element is annotated with `@Override`
## Debugging Issues
To rebuild the user-facing documentation without having to rebuild the entire system, use the `ant docs` target. This will run the markdown generator, Jekyll, and copy the resulting HTML into the appengine build tree. You will at least need to have run `ant noplay` or `ant` to have the rest of the build tree set up for testing the changes with `dev_appserver`.
### Generic-looking tooltip
Consider the following code:
```java
@SimpleProperty(description = "foobar")
pubilc void Foo(String foo) {}
@SimpleProperty
public String Foo() { return ""; }
```
The reference documentation will have the description as "Property for Foo" whereas the block tooltip will be "foobar". The reason for this is because
### Tooltip and reference swapped
Consider the following code:
```java
/**
* Javadoc description.
*/
@SimpleProperty
public void Foo(String foo) {}
@SimpleProperty(description = "Tooltip")
public String Foo() { return ""; }
```
The reference documentation will be "Tooltip" and the tooltip will be "Javadoc description." The reason for this is because the first Foo will gain the Javadoc as its tooltip (non-empty Javadoc plus no description provided). The second one
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment