@@ -41,7 +41,10 @@ Having correct samples in Javadoc has never been easier!

## Use in a Maven Project

Add the doclet to your Maven Javadoc plugin configuration (as done [here](https://github.com/jtulach/codesnippet4javadoc/commit/16fd9cf7114d9ddc087cb3c0fcaec3d44acb2ed2#diff-74a104b8e241b27d093230d1c9a23dc4R16)):
The bits of the [codesnippet-doclet](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22codesnippet-doclet%22)
are being uploaded to [Maven central](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22codesnippet-doclet%22).
Add the doclet to your Maven Javadoc plugin configuration
(as done [here](https://github.com/jtulach/codesnippet4javadoc/commit/16fd9cf7114d9ddc087cb3c0fcaec3d44acb2ed2#diff-74a104b8e241b27d093230d1c9a23dc4R16)):

```xml
<plugin>
@@ -53,7 +56,7 @@ Add the doclet to your Maven Javadoc plugin configuration (as done [here](https:
<docletArtifact>
<groupId>org.apidesign.javadoc</groupId>
<artifactId>codesnippet-doclet</artifactId>
<version>0.10</version> <!-- or any newer version -->
<version>0.12</version> <!-- or any newer version -->
</docletArtifact>
<!-- if you want to reference snippets from your test directory, also include -->
<additionalparam>-snippetpath "${basedir}/src/test/java"</additionalparam>
@@ -130,6 +133,22 @@ $ javadoc \
```
and warning will be printed for every element without the **@since** tag.

## Hide @Deprecated Classes

The code snippet doclet can, since version 0.11, exclude Javadoc elements annotated by some annotation from the Javadoc.
This is especially useful with `java.lang.Deprecated` annotation, by using:

```bash
$ javadoc \
-doclet org.apidesign.javadoc.codesnippet.Doclet \
-docletpath path/to/downloaded/codesnippet-doclet.jar \
-hiddingannotation java.lang.Deprecated
```

one can eliminate deprecated fields and methods from the Javadoc and also hide classes and interfaces from the Javadoc
overview (however their individual HTML pages still remain in Javadoc for those who keep permanent links to them). One
can use the `-hddingannotation` parameter with other annotations as well and even repeat the parameter multiple times
to hide multiple annotations at once.

## License

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.java</groupId>
<artifactId>jvnet-parent</artifactId>
<version>5</version>
<relativePath />
</parent>
<groupId>org.apidesign.javadoc</groupId>
<artifactId>codesnippet-doclet-test</artifactId>
<name>Codesnippet Doclet Test</name>
<version>0.12</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>codesnippet-doclet</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
<version>6.9.10</version>
</dependency>
<dependency>
<groupId>com.github.marschall</groupId>
<artifactId>memoryfilesystem</artifactId>
<version>0.9.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>

<scm>
<tag>release-0.12</tag>
</scm>
</project>
@@ -0,0 +1,23 @@
/**
* Codesnippet Javadoc Doclet
* Copyright (C) 2015-2017 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.0 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://opensource.org/licenses/GPL-3.0.
*/
package org.apidesign.javadoc.codesnippet;

public final class Tests {
private Tests() {
}
}
@@ -0,0 +1,18 @@
/**
* Codesnippet Javadoc Doclet
* Copyright (C) 2015-2017 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.0 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://opensource.org/licenses/GPL-3.0.
*/
package org.apidesign.javadoc.codesnippet;
@@ -52,6 +52,32 @@ public SnippetsTest() {
assertEquals("<b>public</b> <b>interface</b> {@link ahoj.I} {\n}\n", r);
}

@Test
public void properIndentationForMultipleFinish() throws Exception {
String c1
= "package ahoj;\n"
+ "// BEGIN: xyz\n"
+ "public interface I {\n"
+ " public void call() {\n"
+ "// FINISH: xyz\n"
+ " }\n"
+ "}"
+ "";
Path src = createPath(1, "I.java", c1);

Snippets snippets = new Snippets(null);
addPath(snippets, src.getParent());
String r = snippets.findSnippet(null, "xyz");

assertEquals(""
+ "<b>public</b> <b>interface</b> {@link ahoj.I} {\n"
+ " <b>public</b> <b>void</b> call() {\n"
+ " }\n"
+ "}\n"
+ "", r
);
}

@Test public void testJavaLangImportRecognized() throws Exception {
String c1
= "package ahoj;\n"
@@ -300,6 +326,81 @@ public SnippetsTest() {
}
}

@Test public void testLineCommentsInItalic() throws Exception {
String c1
= "package ahoj;\n"
+ "public class C {\n"
+ " // BEGIN: comment\n"
+ " class Comment {\n"
+ " // no keywords for this comment\n"
+ " private int x;\n"
+ " }\n"
+ " // END: comment\n"
+ "}\n"
+ "";
Path src = createPath(1, "C.java", c1);

Snippets snippets = new Snippets(null);
addPath(snippets, src.getParent());
String r = snippets.findSnippet(null, "comment");

String assume = ""
+ "<b>class</b> Comment {\n"
+ " <em>// no keywords for this comment</em>\n"
+ " <b>private</b> <b>int</b> x;\n"
+ "}\n";

assertEquals(assume, r);
}

@Test public void testStrings() throws Exception {
String c1
= "package ahoj;\n"
+ "public class C {\n"
+ " // BEGIN: str\n"
+ " public String str = \"this is my long string\";\n"
+ " private int length = str.length();\n"
+ " // END: str\n"
+ "}\n"
+ "";
Path src = createPath(1, "C.java", c1);

Snippets snippets = new Snippets(null);
addPath(snippets, src.getParent());
String r = snippets.findSnippet(null, "str");

String assume = ""
+ "<b>public</b> {@link java.lang.String} str = <em>\"this is my long string\"</em>;\n"
+ "<b>private</b> <b>int</b> length = str.length();\n"
+ "";

assertEquals(assume, r);
}

@Test public void testConcatenateStrings() throws Exception {
String c1
= "package ahoj;\n"
+ "import net.java.html.js.JavaScriptBody;\n"
+ "public class C {\n"
+ " private static String space = \" \";\n"
+ " // BEGIN: str\n"
+ " private static String str = \"Jaroslav\" + space + \"Tulach\";\n"
+ " // END: str\n"
+ "}\n"
+ "";
Path src = createPath(1, "C.java", c1);

Snippets snippets = new Snippets(null);
addPath(snippets, src.getParent());
String r = snippets.findSnippet(null, "str");

String assume = ""
+ "<b>private</b> <b>static</b> {@link java.lang.String} str = <em>\"Jaroslav\"</em> + space + <em>\"Tulach\"</em>;\n"
+ "";

assertEquals(assume, r);
}

@Test public void testInXML() throws Exception {
String c1
= "<!-- BEGIN: clazz -->\n"
@@ -10,7 +10,7 @@
<groupId>org.apidesign.javadoc</groupId>
<artifactId>codesnippet-doclet</artifactId>
<name>Codesnippet Doclet Code</name>
<version>0.11</version>
<version>0.12</version>
<properties>
<tools.jar>${java.home}/../lib/tools.jar</tools.jar>
</properties>
@@ -23,18 +23,6 @@
<scope>system</scope>
<systemPath>${tools.jar}</systemPath>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
<version>6.9.10</version>
</dependency>
<dependency>
<groupId>com.github.marschall</groupId>
<artifactId>memoryfilesystem</artifactId>
<version>0.7.7</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
@@ -51,6 +39,6 @@
</build>

<scm>
<tag>release-0.11</tag>
<tag>release-0.12</tag>
</scm>
</project>
@@ -391,7 +391,7 @@ static String javaName(Path file1) {
return name.endsWith(".java") ? name.substring(0, name.length() - 5) : null;
}

private static Pattern WORDS = Pattern.compile("\\w+");
private static final Pattern WORDS = Pattern.compile("(\\w+)|(//.*)\n|(\"[^\"]*\")");
static String boldJavaKeywords(String text, Map<String,String> imports, Set<String> packages) {
Matcher m = WORDS.matcher(text);
StringBuffer sb = new StringBuffer();
@@ -454,6 +454,14 @@ static String boldJavaKeywords(String text, Map<String,String> imports, Set<Stri
append = "<b>" + m.group(0) + "</b>";
break;
default:
if (m.group(0).startsWith("//")) {
append = "<em>" + m.group(0).substring(0, m.group(0).length() - 1) + "</em>\n";
break;
}
if (m.group(0).startsWith("\"")) {
append = "<em>" + m.group(0) + "</em>";
break;
}
String fqn;
fqn = imports.get(m.group(0));
if (fqn == null) {
@@ -525,6 +533,35 @@ boolean isHiddingAnnotation(String name) {
return this.hiddenAnno != null && this.hiddenAnno.contains(name);
}

static int findMissingIndentation(String unclosedText) {
int closed = 0;
int i = unclosedText.length() - 1;
while (i >= 0) {
char ch = unclosedText.charAt(i--);
if (ch == '}') {
closed++;
}
if (ch == '{') {
if (closed-- == 0) {
break;
}
}
}
int spaces = 0;
while (i >= 0) {
char ch = unclosedText.charAt(i--);
if (ch == ' ') {
spaces++;
continue;
}
if (ch == '\n' || ch == '\r') {
break;
}
spaces = 0;
}
return spaces;
}

private final class Item implements CharSequence {

private StringBuilder sb = new StringBuilder();
@@ -591,6 +628,10 @@ public String toString(boolean finish, Map<String,String> imports, Set<String> p
int end = countChar(sb, '}');
if (finish) {
for (int i = 0; i < open - end; i++) {
int missingBraceIndent = findMissingIndentation(sb.toString());
while (missingBraceIndent-- > 0) {
sb.append(" ");
}
sb.append("}\n");
}
}
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apidesign.javadoc</groupId>
<artifactId>pom</artifactId>
<version>0.11</version>
<version>0.12</version>
<packaging>pom</packaging>
<name>Codesnippet Javadoc Doclet</name>
<parent>
@@ -30,7 +30,7 @@
<connection>scm:git:https://github.com/jtulach/codesnippet4javadoc.git</connection>
<developerConnection>scm:git:https://github.com/jtulach/codesnippet4javadoc.git</developerConnection>
<url>https://github.com/jtulach/codesnippet4javadoc</url>
<tag>release-0.11</tag>
<tag>release-0.12</tag>
</scm>
<repositories>
<repository>
@@ -110,6 +110,7 @@
</build>
<modules>
<module>doclet</module>
<module>doclet-test</module>
<module>testing</module>
</modules>
<dependencyManagement>
@@ -4,7 +4,7 @@
<parent>
<groupId>org.apidesign.javadoc</groupId>
<artifactId>pom</artifactId>
<version>0.11</version>
<version>0.12</version>
</parent>
<artifactId>testing</artifactId>
<name>Codesnippet for Javadoc Tests</name>