8144287: Enhance DocTree API to support @index javadoc tags.
authorksrini
Tue, 01 Dec 2015 07:10:35 -0800
changeset 34567 c74f68484156
parent 34566 071e47e4ae75
child 34568 afc0330fa0d4
8144287: Enhance DocTree API to support @index javadoc tags. Reviewed-by: jjg
langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java
langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java
langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/IndexTree.java
langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java
langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java
langtools/test/com/sun/javadoc/testSearch/TestSearch.java
langtools/test/tools/javac/doctree/DocCommentTester.java
langtools/test/tools/javac/doctree/IndexTest.java
langtools/test/tools/javac/lib/DPrinter.java
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java	Tue Dec 01 07:10:35 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -110,6 +110,12 @@
         IDENTIFIER,
 
         /**
+         * Used for instances of {@index term optional-descr}
+         * representing a search term.
+         */
+        INDEX("index"),
+
+        /**
          * Used for instances of {@link InheritDocTree}
          * representing an @inheritDoc tag.
          */
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTreeVisitor.java	Tue Dec 01 07:10:35 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -138,6 +138,14 @@
     R visitIdentifier(IdentifierTree node, P p);
 
     /**
+     * Visits an IndexTree node.
+     * @param node the node being visited
+     * @param p a parameter value
+     * @return a result value
+     */
+    R visitIndex(IndexTree node, P p);
+
+    /**
      * Visits an InheritDocTree node.
      * @param node the node being visited
      * @param p a parameter value
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/IndexTree.java	Tue Dec 01 07:10:35 2015 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.source.doctree;
+
+import java.util.List;
+
+/**
+ * A tree node for an @index or @index inline tag.
+ *
+ * <p>
+ * {&#064;index keyword optional description} <br>
+ *
+ * @since 1.9
+ */
+@jdk.Exported
+public interface IndexTree extends InlineTagTree {
+    /**
+     * Returns the specified search term.
+     * @return the search term
+     */
+    DocTree getSearchTerm();
+
+    /**
+     * Returns the description, if any.
+     * @return the description
+     */
+    List<? extends DocTree> getDescription();
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeScanner.java	Tue Dec 01 07:10:35 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package com.sun.source.util;
 
 import com.sun.source.doctree.*;
+import com.sun.tools.javac.tree.DCTree.DCIndex;
 
 
 /**
@@ -255,6 +256,20 @@
      * @return the result of scanning
      */
     @Override
+    public R visitIndex(IndexTree node, P p) {
+        R r = scan(node.getSearchTerm(), p);
+        r = scanAndReduce(node.getDescription(), p, r);
+        return r;
+    }
+
+    /**
+     * {@inheritDoc} This implementation returns {@code null}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of scanning
+     */
+    @Override
     public R visitInheritDoc(InheritDocTree node, P p) {
         return null;
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/SimpleDocTreeVisitor.java	Tue Dec 01 07:10:35 2015 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -224,6 +224,18 @@
      * @return  the result of {@code defaultAction}
      */
     @Override
+    public R visitIndex(IndexTree node, P p) {
+        return defaultAction(node, p);
+    }
+
+    /**
+     * {@inheritDoc} This implementation calls {@code defaultAction}.
+     *
+     * @param node {@inheritDoc}
+     * @param p {@inheritDoc}
+     * @return  the result of {@code defaultAction}
+     */
+    @Override
     public R visitInheritDoc(InheritDocTree node, P p) {
         return defaultAction(node, p);
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java	Tue Dec 01 07:10:35 2015 -0800
@@ -578,12 +578,49 @@
     }
 
     /**
+     * Read a term ie. one word.
+     * It is an error if the beginning of the next tag is detected.
+     */
+    @SuppressWarnings("fallthrough")
+    protected DCText inlineWord() {
+        int pos = bp;
+        int depth = 0;
+        loop:
+        while (bp < buflen) {
+            switch (ch) {
+                case '\n':
+                    newline = true;
+                    // fallthrough
+
+                case '\r': case '\f': case ' ': case '\t':
+                    return m.at(pos).Text(newString(pos, bp));
+
+                case '@':
+                    if (newline)
+                        break loop;
+
+                case '{':
+                    depth++;
+                    break;
+
+                case '}':
+                    if (depth == 0 || --depth == 0)
+                        return m.at(pos).Text(newString(pos, bp));
+                    break;
+            }
+            newline = false;
+            nextChar();
+        }
+        return null;
+    }
+
+    /**
      * Read general text content of an inline tag, including HTML entities and elements.
      * Matching pairs of { } are skipped; the text is terminated by the first
      * unmatched }. It is an error if the beginning of the next tag is detected.
      */
     @SuppressWarnings("fallthrough")
-    protected List<DCTree> inlineContent() {
+    private List<DCTree> inlineContent() {
         ListBuffer<DCTree> trees = new ListBuffer<>();
 
         skipWhitespace();
@@ -614,6 +651,8 @@
                     break;
 
                 case '{':
+                    if (textStart == -1)
+                        textStart = bp;
                     newline = false;
                     depth++;
                     nextChar();
@@ -1022,6 +1061,28 @@
                 }
             },
 
+            // @index search-term options-description
+            new TagParser(Kind.INLINE, DCTree.Kind.INDEX) {
+                public DCTree parse(int pos) throws ParseException {
+                    skipWhitespace();
+                    if (ch == '}') {
+                        throw new ParseException("dc.no.content");
+                    }
+                    DCTree term = ch == '"' ? quotedString() : inlineWord();
+                    if (term == null) {
+                        throw new ParseException("dc.no.content");
+                    }
+                    skipWhitespace();
+                    List<DCTree> description = List.nil();
+                    if (ch != '}') {
+                        description = inlineContent();
+                    } else {
+                        nextChar();
+                    }
+                    return m.at(pos).Index(term, description);
+                }
+            },
+
             // {@inheritDoc}
             new TagParser(Kind.INLINE, DCTree.Kind.INHERIT_DOC) {
                 public DCTree parse(int pos) throws ParseException {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java	Tue Dec 01 07:10:35 2015 -0800
@@ -408,6 +408,36 @@
         }
     }
 
+    public static class DCIndex extends DCInlineTag implements IndexTree {
+        public final DCTree term;
+        public final List<DCTree> description;
+
+        DCIndex(DCTree term, List<DCTree> description) {
+            this.term = term;
+            this.description = description;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Kind getKind() {
+            return Kind.INDEX;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public <R, D> R accept(DocTreeVisitor<R, D> v, D d) {
+            return v.visitIndex(this, d);
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public DocTree getSearchTerm() {
+            return term;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public java.util.List<? extends DocTree> getDescription() {
+            return description;
+        }
+    }
+
     public static class DCInheritDoc extends DCInlineTag implements InheritDocTree {
         @Override @DefinedBy(Api.COMPILER_TREE)
         public Kind getKind() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocPretty.java	Tue Dec 01 07:10:35 2015 -0800
@@ -270,6 +270,24 @@
     }
 
     @DefinedBy(Api.COMPILER_TREE)
+    public Void visitIndex(IndexTree node, Void p) {
+        try {
+            print("{");
+            printTagName(node);
+            print(" ");
+            print(node.getSearchTerm());
+            if (!node.getDescription().isEmpty()) {
+                print(" ");
+                print(node.getDescription());
+            }
+            print("}");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+        return null;
+    }
+
+    @DefinedBy(Api.COMPILER_TREE)
     public Void visitInheritDoc(InheritDocTree node, Void p) {
         try {
             print("{");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java	Tue Dec 01 07:10:35 2015 -0800
@@ -50,6 +50,7 @@
 import com.sun.tools.javac.tree.DCTree.DCEntity;
 import com.sun.tools.javac.tree.DCTree.DCErroneous;
 import com.sun.tools.javac.tree.DCTree.DCIdentifier;
+import com.sun.tools.javac.tree.DCTree.DCIndex;
 import com.sun.tools.javac.tree.DCTree.DCInheritDoc;
 import com.sun.tools.javac.tree.DCTree.DCLink;
 import com.sun.tools.javac.tree.DCTree.DCLiteral;
@@ -224,6 +225,12 @@
         return tree;
     }
 
+    public DCIndex Index(DCTree term, List<DCTree> description) {
+        DCIndex tree = new DCIndex(term, description);
+        tree.pos = pos;
+        return tree;
+    }
+
     public DCInheritDoc InheritDoc() {
         DCInheritDoc tree = new DCInheritDoc();
         tree.pos = pos;
--- a/langtools/test/com/sun/javadoc/testSearch/TestSearch.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/test/com/sun/javadoc/testSearch/TestSearch.java	Tue Dec 01 07:10:35 2015 -0800
@@ -71,7 +71,8 @@
 
     @Test
     void test3() {
-        javadoc("-d", "out-3", "-noindex", "-sourcepath", testSrc,
+        javadoc("-d", "out-3", "-noindex", "-Xdoclint:none",
+                "-sourcepath", testSrc,
                 "-use", "pkg", "pkg1", "pkg2", "pkg3");
         checkExit(Exit.OK);
         checkSearchOutput(false);
@@ -86,7 +87,8 @@
 
     @Test
     void test4() {
-        javadoc("-d", "out-4", "-html5", "-sourcepath", testSrc,
+        javadoc("-d", "out-4", "-html5", "-Xdoclint:none",
+                "-sourcepath", testSrc,
                 "-use", "pkg", "pkg1", "pkg2", "pkg3");
         checkExit(Exit.OK);
         checkSearchOutput(true);
@@ -101,7 +103,8 @@
 
     @Test
     void test5() {
-        javadoc("-d", "out-5", "-noindex", "-html5", "-sourcepath", testSrc,
+        javadoc("-d", "out-5", "-noindex", "-html5", "-Xdoclint:none",
+                "-sourcepath", testSrc,
                 "-use", "pkg", "pkg1", "pkg2", "pkg3");
         checkExit(Exit.OK);
         checkSearchOutput(false);
@@ -116,7 +119,8 @@
 
     @Test
     void test6() {
-        javadoc("-d", "out-6", "-nocomment", "-sourcepath", testSrc,
+        javadoc("-d", "out-6", "-nocomment", "-Xdoclint:none",
+                "-sourcepath", testSrc,
                 "-use", "pkg", "pkg1", "pkg2", "pkg3");
         checkExit(Exit.OK);
         checkSearchOutput(true);
@@ -131,7 +135,8 @@
 
     @Test
     void test7() {
-        javadoc("-d", "out-7", "-nodeprecated", "-sourcepath", testSrc,
+        javadoc("-d", "out-7", "-nodeprecated", "-Xdoclint:none",
+                "-sourcepath", testSrc,
                 "-use", "pkg", "pkg1", "pkg2", "pkg3");
         checkExit(Exit.OK);
         checkSearchOutput(true);
--- a/langtools/test/tools/javac/doctree/DocCommentTester.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/test/tools/javac/doctree/DocCommentTester.java	Tue Dec 01 07:10:35 2015 -0800
@@ -444,6 +444,18 @@
                 return null;
             }
 
+            @Override
+            public Void visitIndex(IndexTree node, Void p) {
+                header(node);
+                indent(+1);
+                print("term", node.getSearchTerm());
+                print("description", node.getDescription());
+                indent(-1);
+                indent();
+                out.println("]");
+                return null;
+            }
+
             public Void visitInheritDoc(InheritDocTree node, Void p) {
                 header(node, "");
                 return null;
@@ -619,11 +631,19 @@
                 throw new UnsupportedOperationException("Not supported yet.");
             }
 
+            /*
+             * Use this method to start printing a multi-line representation of a
+             * DocTree node. The representation should be termintated by calling
+             * out.println("]").
+             */
             void header(DocTree node) {
                 indent();
                 out.println(simpleClassName(node) + "[" + node.getKind() + ", pos:" + ((DCTree) node).pos);
             }
 
+            /*
+             * Use this method to print a single-line representation of a DocTree node.
+             */
             void header(DocTree node, String rest) {
                 indent();
                 out.println(simpleClassName(node) + "[" + node.getKind() + ", pos:" + ((DCTree) node).pos
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/doctree/IndexTest.java	Tue Dec 01 07:10:35 2015 -0800
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8144287
+ * @summary extend com.sun.source API to support parsing javadoc comments
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.file
+ *          jdk.compiler/com.sun.tools.javac.tree
+ *          jdk.compiler/com.sun.tools.javac.util
+ * @build DocCommentTester
+ * @run main DocCommentTester IndexTest.java
+ */
+
+class IndexTest {
+    /**
+     * abc {@index xyz} def
+     */
+    void simple_term() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, xyz]
+      description: empty
+    ]
+    Text[TEXT, pos:17, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index lmn pqr stu} def
+     */
+    void simple_term_with_description() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, lmn]
+      description: 1
+        Text[TEXT, pos:17, pqr_stu]
+    ]
+    Text[TEXT, pos:25, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index ijk {lmn opq} } def
+     */
+    void phrase_with_curly_description() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, ijk]
+      description: 1
+        Text[TEXT, pos:17, {lmn_opq}_]
+    ]
+    Text[TEXT, pos:28, _def]
+  body: empty
+  block tags: empty
+]
+*/
+    /**
+     * abc {@index ijk lmn
+     * opq
+     * rst
+     * } def
+     */
+    void phrase_with_nl_description() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, ijk]
+      description: 1
+        Text[TEXT, pos:17, lmn|_opq|_rst|_]
+    ]
+    Text[TEXT, pos:33, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index "lmn pqr"} def
+     */
+    void phrase_no_description() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, "lmn_pqr"]
+      description: empty
+    ]
+    Text[TEXT, pos:23, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index "ijk lmn" pqr xyz} def
+     */
+    void phrase_with_description() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, "ijk_lmn"]
+      description: 1
+        Text[TEXT, pos:23, pqr_xyz]
+    ]
+    Text[TEXT, pos:31, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index {@xyz} "{@see xyz}" def}
+     */
+    void term_and_description_with_nested_tag() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 2
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, {@xyz}]
+      description: 1
+        Text[TEXT, pos:20, "{@see_xyz}"_def]
+    ]
+  body: empty
+  block tags: empty
+]
+*/
+    /**
+     * abc {@index @def lmn } xyz
+     */
+    void term_with_at() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, @def]
+      description: 1
+        Text[TEXT, pos:18, lmn_]
+    ]
+    Text[TEXT, pos:23, _xyz]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index ijk@lmn pqr } xyz
+     */
+    void term_with_text_at() { }
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, ijk@lmn]
+      description: 1
+        Text[TEXT, pos:21, pqr_]
+    ]
+    Text[TEXT, pos:26, _xyz]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index ""} def
+     */
+    void empty_index_in_quotes() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Index[INDEX, pos:5
+      term:
+        Text[TEXT, pos:13, ""]
+      description: empty
+    ]
+    Text[TEXT, pos:16, _def]
+  body: empty
+  block tags: empty
+]
+*/
+
+    /**
+     * abc {@index
+     * @return def} xyz
+     */
+    void bad_nl_at_in_term() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 2
+    Text[TEXT, pos:1, abc_]
+    Erroneous[ERRONEOUS, pos:5
+      code: compiler.err.dc.no.content
+      body: {@index
+    ]
+  body: empty
+  block tags: 1
+    Return[RETURN, pos:14
+      description: 1
+        Text[TEXT, pos:22, def}_xyz]
+    ]
+]
+*/
+    /**
+     * abc {@index "xyz } def
+     */
+    void bad_unbalanced_quote() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 2
+    Text[TEXT, pos:1, abc_]
+    Erroneous[ERRONEOUS, pos:5
+      code: compiler.err.dc.no.content
+      body: {@index_"xyz_}_def
+    ]
+  body: empty
+  block tags: empty
+]
+*/
+    /**
+     * abc {@index} def
+     */
+    void bad_no_index() {}
+/*
+DocComment[DOC_COMMENT, pos:1
+  firstSentence: 3
+    Text[TEXT, pos:1, abc_]
+    Erroneous[ERRONEOUS, pos:5
+      code: compiler.err.dc.no.content
+      body: {@index
+    ]
+    Text[TEXT, pos:12, }_def]
+  body: empty
+  block tags: empty
+]
+*/
+
+}
--- a/langtools/test/tools/javac/lib/DPrinter.java	Wed Dec 09 12:50:41 2015 -0800
+++ b/langtools/test/tools/javac/lib/DPrinter.java	Tue Dec 01 07:10:35 2015 -0800
@@ -1049,6 +1049,13 @@
             return visitTree(node, null);
         }
 
+        public Void visitIndex(IndexTree node, Void p) {
+            printString("kind", node.getKind().name());
+            printDocTree("term", node.getSearchTerm());
+            printList("desc", node.getDescription());
+            return visitInlineTag(node, p);
+        }
+
         public Void visitInheritDoc(InheritDocTree node, Void p) {
             return visitInlineTag(node, null);
         }