8025091: VisibleMemberMap.java possible performance improvements
authorksrini
Tue, 24 Apr 2018 11:54:03 -0700
changeset 49879 601277b1d582
parent 49878 2422d4e027b0
child 49880 3714eeb7e473
8025091: VisibleMemberMap.java possible performance improvements 8198890: The standard doclet incorrectly produces wrong method signatures in certain cases. Reviewed-by: jjg
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyUtils.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ImplementedMethods.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberCache.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java
test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java
test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java
test/langtools/jdk/javadoc/doclet/testJavaFX/propgen/PropGen.java
test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java
test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java
test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java
test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java
test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java
test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java
test/langtools/tools/lib/builder/AbstractBuilder.java
test/langtools/tools/lib/builder/ClassBuilder.java
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Tue Apr 24 11:54:03 2018 -0700
@@ -45,14 +45,12 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 import static javax.lang.model.element.Modifier.*;
 
@@ -134,7 +132,7 @@
     /**
      * Create the summary table for this element.
      * The table should be created and initialized if needed, and configured
-     * so that it is ready to add content with {@link Table#addRows(Content[])}
+     * so that it is ready to add content with {@link Table#addRow(Content[])}
      * and similar methods.
      *
      * @return the summary table
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -37,13 +37,11 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 
-
 /**
  * Writes annotation type field documentation in HTML format.
  *
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -41,10 +41,8 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * Generate the Class Information Page.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -45,14 +45,11 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
 import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * Generate the Class Information Page.
@@ -122,7 +119,7 @@
             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
             moduleNameDiv.addContent(Contents.SPACE);
             moduleNameDiv.addContent(getModuleLink(mdle,
-                    new StringContent(mdle.getQualifiedName().toString())));
+                    new StringContent(mdle.getQualifiedName())));
             div.addContent(moduleNameDiv);
         }
         PackageElement pkg = utils.containingPackage(typeElement);
@@ -373,8 +370,8 @@
     @Override
     public void addSubClassInfo(Content classInfoTree) {
         if (utils.isClass(typeElement)) {
-            if (typeElement.getQualifiedName().toString().equals("java.lang.Object") ||
-                    typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) {
+            if (typeElement.getQualifiedName().contentEquals("java.lang.Object") ||
+                    typeElement.getQualifiedName().contentEquals("org.omg.CORBA.Object")) {
                 return;    // Don't generate the list, too huge
             }
             Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
@@ -415,8 +412,8 @@
         if (!utils.isInterface(typeElement)) {
             return;
         }
-        if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") ||
-                typeElement.getQualifiedName().toString().equals("java.io.Serializable")) {
+        if (typeElement.getQualifiedName().contentEquals("java.lang.Cloneable") ||
+                typeElement.getQualifiedName().contentEquals("java.io.Serializable")) {
             return;   // Don't generate the list, too big
         }
         Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -38,12 +38,13 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 
 /**
@@ -72,10 +73,9 @@
     public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
         super(writer, typeElement);
 
-        VisibleMemberMap visibleMemberMap = configuration.getVisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS);
-        List<Element> constructors = visibleMemberMap.getMembers(typeElement);
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+        List<? extends Element> constructors = vmt.getVisibleMembers(CONSTRUCTORS);
+
         for (Element constructor : constructors) {
             if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
                 setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import java.util.EnumMap;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -36,6 +38,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
 
 /**
  * Constants and factory methods for common fragments of content
@@ -165,6 +169,8 @@
     public final Content useLabel;
     public final Content valueLabel;
 
+    private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels;
+
     private final Resources resources;
 
     /**
@@ -289,6 +295,13 @@
         typeLabel = getContent("doclet.Type");
         useLabel = getContent("doclet.navClassUse");
         valueLabel = getContent("doclet.Value");
+
+        navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class);
+        navLinkLabels.put(VisibleMemberTable.Kind.INNER_CLASSES, getContent("doclet.navNested"));
+        navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, getContent("doclet.navEnum"));
+        navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField"));
+        navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor"));
+        navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod"));
     }
 
     /**
@@ -393,4 +406,13 @@
         c.addContent(text.substring(start));
         return c; // TODO: should be made immutable
     }
+
+    /**
+     * Returns a content for a visible member kind.
+     * @param kind the visible member table kind.
+     * @return the string content
+     */
+    public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) {
+        return Objects.requireNonNull(navLinkLabels.get(kind));
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -107,7 +107,6 @@
      * For new format.
      *
      * @throws DocletException if there is a problem while writing the other files
-     * @see jdk.doclet.DocletEnvironment
      */
     @Override // defined by AbstractDoclet
     protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
@@ -242,7 +241,7 @@
         List<TypeElement> list = new ArrayList<>(arr);
         ListIterator<TypeElement> iterator = list.listIterator();
         for (TypeElement klass : list) {
-            if (utils.isHidden(klass) ||
+            if (utils.hasHiddenTag(klass) ||
                     !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) {
                 continue;
             }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Tue Apr 24 11:54:03 2018 -0700
@@ -69,13 +69,11 @@
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
@@ -94,9 +92,8 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 import static com.sun.source.doctree.DocTree.Kind.*;
 import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER;
@@ -302,11 +299,12 @@
         TypeElement enclosing = utils.getEnclosingTypeElement(method);
         List<? extends TypeMirror> intfacs = enclosing.getInterfaces();
         ExecutableElement overriddenMethod = utils.overriddenMethod(method);
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(enclosing);
         // Check whether there is any implementation or overridden info to be
         // printed. If no overridden or implementation info needs to be
         // printed, do not print this section.
         if ((!intfacs.isEmpty()
-                && new ImplementedMethods(method, this.configuration).build().isEmpty() == false)
+                && vmt.getImplementedMethods(method).isEmpty() == false)
                 || overriddenMethod != null) {
             MethodWriterImpl.addImplementsInfo(this, method, dl);
             if (overriddenMethod != null) {
@@ -1078,10 +1076,11 @@
 
             // Find the enclosing type where the method is actually visible
             // in the inheritance hierarchy.
+            ExecutableElement overriddenMethod = null;
             if (refMem.getKind() == ElementKind.METHOD) {
-                VisibleMemberMap vmm = configuration.getVisibleMemberMap(containing,
-                        VisibleMemberMap.Kind.METHODS);
-                ExecutableElement overriddenMethod = vmm.getVisibleMethod((ExecutableElement)refMem);
+                VisibleMemberTable vmt = configuration.getVisibleMemberTable(containing);
+                overriddenMethod = vmt.getOverriddenMethod((ExecutableElement)refMem);
+
                 if (overriddenMethod != null)
                     containing = utils.getEnclosingTypeElement(overriddenMethod);
             }
@@ -1112,6 +1111,10 @@
                 if (refMemName.indexOf('(') < 0) {
                     refMemName += utils.makeSignature((ExecutableElement)refMem, true);
                 }
+                if (overriddenMethod != null) {
+                    // The method to actually link.
+                    refMem = overriddenMethod;
+                }
             }
 
             text = plainOrCode(kind == LINK_PLAIN, new StringContent(refMemName));
@@ -1596,7 +1599,7 @@
      * {@literal <a href="./com/sun/javadoc/package-summary.html">The package Page</a>}
      *
      * @param element the Element object whose documentation is being written.
-     * @param text the text being written.
+     * @param tt the text being written.
      *
      * @return the text, with all the relative links redirected to work.
      */
@@ -1671,7 +1674,7 @@
      * Add the annotation types of the executable receiver.
      *
      * @param method the executable to write the receiver annotations for.
-     * @param descList list of annotation description.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1718,7 +1721,7 @@
      * Adds the annotatation types for the given Element.
      *
      * @param element the element to write annotations for.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1732,7 +1735,7 @@
      *
      * @param indent the number of extra spaces to indent the annotations.
      * @param element the element to write annotations for.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1758,9 +1761,9 @@
      * the given doc.
      *
      * @param indent the number of extra spaces to indent the annotations.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param linkBreak if true, add new line between each member value.
-     * @return an array of strings representing the annotations being
+     * @return a list of strings representing the annotations being
      *         documented.
      */
     private List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList, boolean linkBreak) {
@@ -1781,10 +1784,10 @@
      * annotations should be returned without any filtering.
      *
      * @param indent the number of extra spaces to indent the annotations.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param linkBreak if true, add new line between each member value.
      * @param isJava5DeclarationLocation
-     * @return an array of strings representing the annotations being
+     * @return a list of strings representing the annotations being
      *         documented.
      */
     public List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -40,13 +40,12 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * Writes method documentation in HTML format.
@@ -383,13 +382,13 @@
             return;
         }
         Contents contents = writer.contents;
-        ImplementedMethods implementedMethodsFinder =
-                new ImplementedMethods(method, writer.configuration);
+        VisibleMemberTable vmt = writer.configuration
+                .getVisibleMemberTable(utils.getEnclosingTypeElement(method));
         SortedSet<ExecutableElement> implementedMethods =
                 new TreeSet<>(utils.makeOverrideUseComparator());
-        implementedMethods.addAll(implementedMethodsFinder.build());
+        implementedMethods.addAll(vmt.getImplementedMethods(method));
         for (ExecutableElement implementedMeth : implementedMethods) {
-            TypeMirror intfac = implementedMethodsFinder.getMethodHolder(implementedMeth);
+            TypeMirror intfac = vmt.getImplementedMethodHolder(method, implementedMeth);
             intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac);
             Content intfaclink = writer.getLink(new LinkInfoImpl(
                     writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -30,7 +30,6 @@
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
@@ -45,7 +44,7 @@
 import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * The factory that returns HTML writers.
@@ -184,7 +183,7 @@
      */
     @Override
     public MemberSummaryWriter getMemberSummaryWriter(ClassWriter classWriter,
-            VisibleMemberMap.Kind memberType) {
+            VisibleMemberTable.Kind memberType) {
         switch (memberType) {
             case CONSTRUCTORS:
                 return getConstructorWriter(classWriter);
@@ -209,7 +208,7 @@
      */
     @Override
     public MemberSummaryWriter getMemberSummaryWriter(AnnotationTypeWriter annotationTypeWriter,
-            VisibleMemberMap.Kind memberType) {
+            VisibleMemberTable.Kind memberType) {
         switch (memberType) {
             case ANNOTATION_TYPE_FIELDS:
                 return (AnnotationTypeFieldWriterImpl)
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Tue Apr 24 11:54:03 2018 -0700
@@ -30,6 +30,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedSet;
 
 import javax.lang.model.element.Element;
@@ -48,7 +49,9 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Factory for navigation bar.
@@ -414,28 +417,28 @@
             case CLASS:
                 if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
                     addAnnotationTypeSummaryLink("doclet.navField",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, listContents);
+                            ANNOTATION_TYPE_FIELDS, listContents);
                     addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
+                            ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
                     addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
+                            ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
                 } else {
                     TypeElement typeElement = (TypeElement) element;
-                    for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
-                        if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+                    for (VisibleMemberTable.Kind kind : summarySet) {
+                        if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
-                        if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+                        if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
                         AbstractMemberWriter writer
                                 = ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
                         if (writer == null) {
-                            addContentToList(listContents,
-                                    contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+                            addContentToList(listContents, contents.getNavLinkLabelContent(kind));
                         } else {
                             addTypeSummaryLink(memberSummaryBuilder.members(kind),
-                                    memberSummaryBuilder.getVisibleMemberMap(kind), listContents);
+                                    memberSummaryBuilder.getVisibleMemberTable(),
+                                    kind, listContents);
                         }
                     }
                 }
@@ -487,24 +490,25 @@
      * Add the navigation summary link.
      *
      * @param members members to be linked
-     * @param visibleMemberMap the visible inherited members map
+     * @param vmt the visible member table
+     * @param kind the visible member kind
      * @param listContents the list of contents
      */
     private void addTypeSummaryLink(SortedSet<? extends Element> members,
-            VisibleMemberMap visibleMemberMap, List<Content> listContents) {
+            VisibleMemberTable vmt,
+            VisibleMemberTable.Kind kind, List<Content> listContents) {
         if (!members.isEmpty()) {
-            addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+            addTypeSummaryLink(null, kind, true, listContents);
             return;
         }
-
-        SortedSet<TypeElement> visibleClasses = visibleMemberMap.getVisibleClasses();
+        Set<TypeElement> visibleClasses = vmt.getVisibleTypeElements();
         for (TypeElement t : visibleClasses) {
-            if (!configuration.getVisibleMemberMap(t, visibleMemberMap.kind).getLeafMembers().isEmpty()) {
-                addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+            if (configuration.getVisibleMemberTable(t).hasVisibleMembers(kind)) {
+                addTypeSummaryLink(null, kind, true, listContents);
                 return;
             }
         }
-        addTypeSummaryLink(null, visibleMemberMap.kind, false, listContents);
+        addTypeSummaryLink(null, kind, false, listContents);
     }
 
     /**
@@ -515,7 +519,7 @@
      * @param link true if the members are listed and need to be linked
      * @param listContents the list of contents to which the summary will be added
      */
-    private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberMap.Kind kind, boolean link,
+    private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberTable.Kind kind, boolean link,
             List<Content> listContents) {
         switch (kind) {
             case CONSTRUCTORS:
@@ -601,17 +605,17 @@
      * Add the navigation Type summary link.
      *
      * @param label the label to be added
-     * @param type the kind of member being documented
+     * @param kind the kind of member being documented
      * @param listContents the list of contents to which the summary will be added
      */
-    private void addAnnotationTypeSummaryLink(String label, VisibleMemberMap.Kind type, List<Content> listContents) {
+    private void addAnnotationTypeSummaryLink(String label, VisibleMemberTable.Kind kind, List<Content> listContents) {
         AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder.
-                getMemberSummaryWriter(type));
+                getMemberSummaryWriter(kind));
         if (writer == null) {
             addContentToList(listContents, contents.getContent(label));
         } else {
-            boolean link = !memberSummaryBuilder.getVisibleMemberMap(type).noVisibleMembers();
-            switch (type) {
+            boolean link = memberSummaryBuilder.getVisibleMemberTable().hasVisibleMembers(kind);
+            switch (kind) {
                 case ANNOTATION_TYPE_FIELDS:
                     if (link) {
                         addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_SUMMARY,
@@ -657,20 +661,20 @@
                     addAnnotationTypeDetailLink(listContents);
                 } else {
                     TypeElement typeElement = (TypeElement) element;
-                    for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
+                    for (VisibleMemberTable.Kind kind : detailSet) {
                         AbstractMemberWriter writer
                                 = ((AbstractMemberWriter) memberSummaryBuilder.
                                         getMemberSummaryWriter(kind));
-                        if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+                        if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
-                        if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+                        if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
                         if (writer == null) {
-                            addContentToList(listContents, contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+                            addContentToList(listContents, contents.getNavLinkLabelContent(kind));
                         } else {
-                            addTypeDetailLink(kind, !memberSummaryBuilder.members(kind).isEmpty(), listContents);
+                            addTypeDetailLink(kind, memberSummaryBuilder.hasMembers(kind), listContents);
                         }
                     }
                 }
@@ -693,7 +697,7 @@
      * @param link true if the members are listed and need to be linked
      * @param listContents the list of contents to which the detail will be added.
      */
-    protected void addTypeDetailLink(VisibleMemberMap.Kind kind, boolean link, List<Content> listContents) {
+    protected void addTypeDetailLink(VisibleMemberTable.Kind kind, boolean link, List<Content> listContents) {
         switch (kind) {
             case CONSTRUCTORS:
                 if (link) {
@@ -744,25 +748,25 @@
         TypeElement annotationType = (TypeElement) element;
         AbstractMemberWriter writerField
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_FIELDS));
         AbstractMemberWriter writerOptional
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_OPTIONAL));
         AbstractMemberWriter writerRequired
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_REQUIRED));
         if (writerField != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_FIELDS,
                     !configuration.utils.getAnnotationFields(annotationType).isEmpty(),
                     listContents);
         } else {
             addContentToList(listContents, contents.navField);
         }
         if (writerOptional != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_OPTIONAL,
                     !annotationType.getAnnotationMirrors().isEmpty(), listContents);
         } else if (writerRequired != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_REQUIRED,
                     !annotationType.getAnnotationMirrors().isEmpty(), listContents);
         } else {
             addContentToList(listContents, contents.navAnnotationTypeMember);
@@ -776,7 +780,7 @@
      * @param link true if the member details need to be linked
      * @param listContents the list of contents to which the annotation detail will be added.
      */
-    protected void addAnnotationTypeDetailLink(VisibleMemberMap.Kind type, boolean link, List<Content> listContents) {
+    protected void addAnnotationTypeDetailLink(VisibleMemberTable.Kind type, boolean link, List<Content> listContents) {
         switch (type) {
             case ANNOTATION_TYPE_FIELDS:
                 if (link) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -81,7 +81,7 @@
 
     /**
      * Verify that the only doclet that is using this toolkit is
-     * {@value #TOOLKIT_DOCLET_NAME}.
+     * #TOOLKIT_DOCLET_NAME.
      */
     private boolean isValidDoclet() {
         if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
@@ -102,10 +102,7 @@
     public boolean run(DocletEnvironment docEnv) {
         configuration = getConfiguration();
         configuration.initConfiguration(docEnv);
-        configuration.cmtUtils = new CommentUtils(configuration);
-        configuration.utils = new Utils(configuration);
         utils = configuration.utils;
-        configuration.workArounds = new WorkArounds(configuration);
         messages = configuration.getMessages();
 
         if (!isValidDoclet()) {
@@ -189,7 +186,6 @@
      * TreeWriter generation first to ensure the Class Hierarchy is built
      * first and then can be used in the later generation.
      *
-     * @see jdk.doclet.DocletEnvironment
      * @throws DocletException if there is a problem while generating the documentation
      */
     private void startGeneration(DocletEnvironment docEnv) throws DocletException {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Tue Apr 24 11:54:03 2018 -0700
@@ -26,7 +26,6 @@
 package jdk.javadoc.internal.doclets.toolkit;
 
 import java.io.*;
-import java.lang.ref.*;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -56,9 +55,8 @@
 import jdk.javadoc.internal.doclets.toolkit.util.TypeElementCatalog;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.GetterSetter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 import static javax.tools.Diagnostic.Kind.*;
 
@@ -299,8 +297,6 @@
 
     private List<Pair<String, String>> groupPairs;
 
-    private final Map<TypeElement, EnumMap<Kind, Reference<VisibleMemberMap>>> typeElementMemberCache;
-
     public abstract Messages getMessages();
 
     public abstract Resources getResources();
@@ -331,11 +327,6 @@
 
     public OverviewElement overviewElement;
 
-    // The following three fields provide caches for use by all instances of VisibleMemberMap.
-    public final Map<TypeElement, List<Element>> propertiesCache = new HashMap<>();
-    public final Map<Element, Element> classPropertiesMap = new HashMap<>();
-    public final Map<Element, GetterSetter> getterSetterMap = new HashMap<>();
-
     public DocFileFactory docFileFactory;
 
     /**
@@ -352,6 +343,17 @@
             "jdk.javadoc.internal.doclets.toolkit.resources.doclets";
 
     /**
+     * Primarily used to disable strict checks in the regression
+     * tests allowing those tests to be executed successfully, for
+     * instance, with OpenJDK builds which may not contain FX libraries.
+     */
+    public boolean disableJavaFxStrictChecks = false;
+
+    VisibleMemberCache visibleMemberCache = null;
+
+    public PropertyUtils propertyUtils = null;
+
+    /**
      * Constructs the configurations needed by the doclet.
      *
      * @param doclet the doclet that created this configuration
@@ -363,7 +365,6 @@
         setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
         metakeywords = new MetaKeywords(this);
         groupPairs = new ArrayList<>(0);
-        typeElementMemberCache = new HashMap<>();
     }
 
     private boolean initialized = false;
@@ -374,6 +375,15 @@
         }
         initialized = true;
         this.docEnv = docEnv;
+        // Utils needs docEnv, safe to init now.
+        utils = new Utils(this);
+
+        // Once docEnv and Utils have been initialized, others should be safe.
+        cmtUtils = new CommentUtils(this);
+        workArounds = new WorkArounds(this);
+        visibleMemberCache = new VisibleMemberCache(this);
+        propertyUtils = new PropertyUtils(this);
+
         Splitter specifiedSplitter = new Splitter(docEnv, false);
         specifiedModuleElements = Collections.unmodifiableSet(specifiedSplitter.mset);
         specifiedPackageElements = Collections.unmodifiableSet(specifiedSplitter.pset);
@@ -699,6 +709,13 @@
                         allowScriptInComments = true;
                         return true;
                     }
+                },
+                new Hidden(resources, "--disable-javafx-strict-checks") {
+                    @Override
+                    public boolean process(String opt, List<String> args) {
+                        disableJavaFxStrictChecks = true;
+                        return true;
+                    }
                 }
         };
         Set<Doclet.Option> set = new TreeSet<>();
@@ -1285,17 +1302,7 @@
         return allowScriptInComments;
     }
 
-    public VisibleMemberMap getVisibleMemberMap(TypeElement te, VisibleMemberMap.Kind kind) {
-        EnumMap<Kind, Reference<VisibleMemberMap>> cacheMap = typeElementMemberCache
-                .computeIfAbsent(te, k -> new EnumMap<>(VisibleMemberMap.Kind.class));
-
-        Reference<VisibleMemberMap> vmapRef = cacheMap.get(kind);
-        // recompute, if referent has been garbage collected
-        VisibleMemberMap vMap = vmapRef == null ? null : vmapRef.get();
-        if (vMap == null) {
-            vMap = new VisibleMemberMap(te, kind, this);
-            cacheMap.put(kind, new SoftReference<>(vMap));
-        }
-        return vMap;
+    public synchronized VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+        return visibleMemberCache.getVisibleMemberTable(te);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -31,7 +31,6 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * The interface for writing member summary output.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyUtils.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit;
+
+import java.util.regex.Pattern;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+
+/**
+ * This class provides basic JavaFX property related utility methods.
+ * Refer to the JavaFX conventions in the VisibleMemberTable comments.
+ */
+public class PropertyUtils {
+
+    final TypeMirror jbObservableType;
+
+    final Pattern fxMethodPatterns;
+
+    final boolean javafx;
+
+    final Types typeUtils;
+
+    PropertyUtils(BaseConfiguration configuration) {
+
+        javafx = configuration.javafx;
+
+        typeUtils = configuration.docEnv.getTypeUtils();
+
+        // Disable strict check for JDK's without FX.
+        TypeMirror jboType = configuration.disableJavaFxStrictChecks
+                ? null
+                : configuration.utils.getSymbol("javafx.beans.Observable");
+
+        jbObservableType = jboType != null
+                ? configuration.docEnv.getTypeUtils().erasure(jboType)
+                : null;
+
+        fxMethodPatterns = javafx
+                ? Pattern.compile("[sg]et\\p{Upper}.*||is\\p{Upper}.*")
+                : null;
+    }
+
+    /**
+     * Returns a base name for a property method. Supposing we
+     * have {@code BooleanProperty acmeProperty()}, then "acme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the base name of a property method.
+     */
+    public String getBaseName(ExecutableElement propertyMethod) {
+        String name = propertyMethod.getSimpleName().toString();
+        String baseName = name.substring(0, name.indexOf("Property"));
+        return baseName;
+    }
+
+    /**
+     * Returns a property getter's name. Supposing we have a property
+     * method {@code DoubleProperty acmeProperty()}, then "getAcme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the property getter's name.
+     */
+    public String getGetName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "get" + fnUppercased;
+    }
+
+    /**
+     * Returns an "is" method's name for a property method. Supposing
+     * we have a property method {@code BooleanProperty acmeProperty()},
+     * then "isAcme" will be returned.
+     * @param propertyMethod
+     * @return the property is getter's name.
+     */
+    public String getIsName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "is" + fnUppercased;
+    }
+
+    /**
+     * Returns true if a property method could have an "is" method, meaning
+     * {@code isAcme} could exist for a property method.
+     * @param propertyMethod
+     * @return true if the property could have an "is" method, false otherwise.
+     */
+    public boolean hasIsMethod(ExecutableElement propertyMethod) {
+        String propertyTypeName = propertyMethod.getReturnType().toString();
+        return "boolean".equals(propertyTypeName) ||
+                propertyTypeName.endsWith("BooleanProperty");
+    }
+
+    /**
+     * Returns a property setter's name. Supposing we have a property
+     * method {@code DoubleProperty acmeProperty()}, then "setAcme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the property setter's method name.
+     */
+    public String getSetName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "set" + fnUppercased;
+    }
+
+    /**
+     * Returns true if the given setter method is a valid property setter
+     * method.
+     * @param setterMethod
+     * @return true if setter method, false otherwise.
+     */
+    public boolean isValidSetterMethod(ExecutableElement setterMethod) {
+        return setterMethod.getReturnType().getKind() == TypeKind.VOID;
+    }
+
+    /**
+     * Returns true if the method is a property method.
+     * @param propertyMethod
+     * @return true if the method is a property method, false otherwise.
+     */
+    public boolean isPropertyMethod(ExecutableElement propertyMethod) {
+        if (!javafx ||
+                !propertyMethod.getParameters().isEmpty() ||
+                !propertyMethod.getTypeParameters().isEmpty()) {
+            return false;
+        }
+        String methodName = propertyMethod.getSimpleName().toString();
+        if (!methodName.endsWith("Property") ||
+                fxMethodPatterns.matcher(methodName).matches()) {
+            return false;
+        }
+
+        TypeMirror returnType = propertyMethod.getReturnType();
+        if (jbObservableType == null) {
+            // JavaFX references missing, make a lazy backward compatible check.
+            return returnType.getKind() != TypeKind.VOID;
+        } else {
+            // Apply strict checks since JavaFX references are available
+            returnType = typeUtils.erasure(propertyMethod.getReturnType());
+            return typeUtils.isAssignable(returnType, jbObservableType);
+        }
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -29,10 +29,9 @@
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * The interface for a factory creates writers.
@@ -180,30 +179,30 @@
      * Return the specified member summary writer for a given class.
      *
      * @param classWriter the writer for the class being documented.
-     * @param memberType  the {@link VisibleMemberMap} member type indicating
+     * @param memberType  the {@link VisibleMemberTable} member type indicating
      *                    the type of member summary that should be returned.
      * @return the summary writer for the give class.  Return null if this
      * writer is not supported by the doclet.
      *
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
     public abstract MemberSummaryWriter getMemberSummaryWriter(
-        ClassWriter classWriter, VisibleMemberMap.Kind memberType);
+        ClassWriter classWriter, VisibleMemberTable.Kind memberType);
 
     /**
      * Return the specified member summary writer for a given annotation type.
      *
      * @param annotationTypeWriter the writer for the annotation type being
      *                             documented.
-     * @param memberType  the {@link VisibleMemberMap} member type indicating
+     * @param memberType  the {@link VisibleMemberTable} member type indicating
      *                    the type of member summary that should be returned.
      * @return the summary writer for the give class.  Return null if this
      * writer is not supported by the doclet.
      *
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
     public abstract MemberSummaryWriter getMemberSummaryWriter(
-        AnnotationTypeWriter annotationTypeWriter, VisibleMemberMap.Kind memberType);
+        AnnotationTypeWriter annotationTypeWriter, VisibleMemberTable.Kind memberType);
 
     /**
      * Return the writer for the serialized form.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -25,8 +25,14 @@
 
 package jdk.javadoc.internal.doclets.toolkit.builders;
 
+import java.util.List;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind;
 
 /**
  * The superclass for all member builders.  Member builders are only executed
@@ -42,13 +48,19 @@
  */
 public abstract class AbstractMemberBuilder extends AbstractBuilder {
 
+    final protected TypeElement typeElement;
+
+    final protected VisibleMemberTable visibleMemberTable;
+
     /**
      * Construct a SubBuilder.
      * @param context a context object, providing information used in this run
      *        of the doclet.
      */
-    public AbstractMemberBuilder(Context context) {
+    public AbstractMemberBuilder(Context context, TypeElement typeElement) {
         super(context);
+        this.typeElement = typeElement;
+        visibleMemberTable = configuration.getVisibleMemberTable(typeElement);
     }
 
     /**
@@ -77,4 +89,14 @@
      * @return true if this subbuilder has anything to document
      */
     public abstract boolean hasMembersToDocument();
+
+    /**
+     * Returns a list of visible elements of the specified kind in this
+     * type element.
+     * @param kind of members
+     * @return a list of members
+     */
+    protected List<? extends Element> getVisibleMembers(Kind kind) {
+        return visibleMemberTable.getVisibleMembers(kind);
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -34,7 +34,7 @@
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 
 /**
@@ -50,16 +50,6 @@
 public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder {
 
     /**
-     * The annotation type whose members are being documented.
-     */
-    protected TypeElement typeElement;
-
-    /**
-     * The visible members for the given class.
-     */
-    protected VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the member documentation.
      */
     protected AnnotationTypeFieldWriter writer;
@@ -67,7 +57,7 @@
     /**
      * The list of members being documented.
      */
-    protected List<Element> members;
+    protected List<? extends Element> members;
 
     /**
      * The index of the current member that is being documented at this point
@@ -86,12 +76,10 @@
     protected AnnotationTypeFieldBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeFieldWriter writer,
-            VisibleMemberMap.Kind memberType) {
-        super(context);
-        this.typeElement = typeElement;
+            VisibleMemberTable.Kind memberType) {
+        super(context, typeElement);
         this.writer = writer;
-        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
-        this.members = this.visibleMemberMap.getMembers(typeElement);
+        this.members = getVisibleMembers(memberType);
     }
 
 
@@ -107,7 +95,7 @@
             Context context, TypeElement typeElement,
             AnnotationTypeFieldWriter writer) {
         return new AnnotationTypeFieldBuilder(context, typeElement,
-                    writer, VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
+                    writer, VisibleMemberTable.Kind.ANNOTATION_TYPE_FIELDS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -31,8 +31,8 @@
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for optional annotation type members.
@@ -57,8 +57,7 @@
     private AnnotationTypeOptionalMemberBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeOptionalMemberWriter writer) {
-        super(context, typeElement, writer,
-                VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+        super(context, typeElement, writer, ANNOTATION_TYPE_MEMBER_OPTIONAL);
     }
 
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -34,8 +34,9 @@
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for required annotation type members.
@@ -50,15 +51,6 @@
  */
 public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
 
-    /**
-     * The annotation type whose members are being documented.
-     */
-    protected TypeElement typeElement;
-
-    /**
-     * The visible members for the given class.
-     */
-    protected VisibleMemberMap visibleMemberMap;
 
     /**
      * The writer to output the member documentation.
@@ -68,7 +60,7 @@
     /**
      * The list of members being documented.
      */
-    protected List<Element> members;
+    protected List<? extends Element> members;
 
     /**
      * The index of the current member that is being documented at this point
@@ -87,12 +79,10 @@
     protected AnnotationTypeRequiredMemberBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeRequiredMemberWriter writer,
-            VisibleMemberMap.Kind memberType) {
-        super(context);
-        this.typeElement = typeElement;
+            VisibleMemberTable.Kind memberType) {
+        super(context, typeElement);
         this.writer = writer;
-        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
-        this.members = this.visibleMemberMap.getMembers(typeElement);
+        this.members = getVisibleMembers(memberType);
     }
 
 
@@ -108,8 +98,7 @@
             Context context, TypeElement typeElement,
             AnnotationTypeRequiredMemberWriter writer) {
         return new AnnotationTypeRequiredMemberBuilder(context, typeElement,
-                    writer,
-                    VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
+                writer, ANNOTATION_TYPE_MEMBER_REQUIRED);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,8 +35,9 @@
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds the Constants Summary Page.
@@ -262,9 +263,8 @@
      * @return true if the given package has constant fields to document.
      */
     private boolean hasConstantField (TypeElement typeElement) {
-        VisibleMemberMap visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
-            VisibleMemberMap.Kind.FIELDS);
-        List<Element> fields = visibleMemberMapFields.getLeafMembers();
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+        List<? extends Element> fields = vmt.getVisibleMembers(FIELDS);
         for (Element f : fields) {
             VariableElement field = (VariableElement)f;
             if (field.getConstantValue() != null) {
@@ -279,7 +279,7 @@
      * Return true if the given package name has been printed.  Also
      * return true if the root of this package has been printed.
      *
-     * @param pkgname the name of the package to check.
+     * @param pkg the name of the package to check.
      */
     private boolean hasPrintedPackageIndex(PackageElement pkg) {
         for (PackageElement printedPkg : printedPackageHeaders) {
@@ -298,16 +298,6 @@
     private class ConstantFieldBuilder {
 
         /**
-         * The map used to get the visible variables.
-         */
-        protected VisibleMemberMap visibleMemberMapFields = null;
-
-        /**
-         * The map used to get the visible variables.
-         */
-        protected VisibleMemberMap visibleMemberMapEnumConst = null;
-
-        /**
          * The typeElement that we are examining constants for.
          */
         protected TypeElement typeElement;
@@ -318,10 +308,6 @@
          */
         public ConstantFieldBuilder(TypeElement typeElement) {
             this.typeElement = typeElement;
-            visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.FIELDS);
-            visibleMemberMapEnumConst = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS);
         }
 
         /**
@@ -342,8 +328,10 @@
          * @return the set of visible constant fields for the given type.
          */
         protected SortedSet<VariableElement> members() {
-            List<Element> members = visibleMemberMapFields.getLeafMembers();
-            members.addAll(visibleMemberMapEnumConst.getLeafMembers());
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+            List<Element> members = new ArrayList<>();
+            members.addAll(vmt.getVisibleMembers(FIELDS));
+            members.addAll(vmt.getVisibleMembers(ENUM_CONSTANTS));
             SortedSet<VariableElement> includes =
                     new TreeSet<>(utils.makeGeneralPurposeComparator());
             for (Element element : members) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a constructor.
@@ -57,16 +57,6 @@
     private ExecutableElement currentConstructor;
 
     /**
-     * The class whose constructors are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible constructors for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the constructor documentation.
      */
     private final ConstructorWriter writer;
@@ -74,7 +64,7 @@
     /**
      * The constructors being documented.
      */
-    private final List<Element> constructors;
+    private final List<? extends Element> constructors;
 
     /**
      * Construct a new ConstructorBuilder.
@@ -86,12 +76,9 @@
     private ConstructorBuilder(Context context,
             TypeElement typeElement,
             ConstructorWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS);
-        constructors = visibleMemberMap.getMembers(typeElement);
+        constructors = getVisibleMembers(CONSTRUCTORS);
         for (Element ctor : constructors) {
             if (utils.isProtected(ctor) || utils.isPrivate(ctor)) {
                 writer.setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a enum constants.
@@ -52,16 +52,6 @@
 public class EnumConstantBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose enum constants are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible enum constantss for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the enum constants documentation.
      */
     private final EnumConstantWriter writer;
@@ -69,7 +59,7 @@
     /**
      * The set of enum constants being documented.
      */
-    private final List<Element> enumConstants;
+    private final List<? extends Element> enumConstants;
 
     /**
      * The current enum constant that is being documented at this point
@@ -86,12 +76,9 @@
      */
     private EnumConstantBuilder(Context context,
             TypeElement typeElement, EnumConstantWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        enumConstants = visibleMemberMap.getMembers(typeElement);
+        enumConstants = getVisibleMembers(ENUM_CONSTANTS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.FieldWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a field.
@@ -52,16 +52,6 @@
 public class FieldBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose fields are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible fields for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the field documentation.
      */
     private final FieldWriter writer;
@@ -69,7 +59,7 @@
     /**
      * The list of fields being documented.
      */
-    private final List<Element> fields;
+    private final List<? extends Element> fields;
 
     /**
      * The index of the current field that is being documented at this point
@@ -85,14 +75,11 @@
      * @param writer the doclet specific writer.
      */
     private FieldBuilder(Context context,
-            TypeElement typeElement,
-            FieldWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+                         TypeElement typeElement,
+                         FieldWriter writer) {
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.FIELDS);
-        fields = visibleMemberMap.getLeafMembers();
+        fields = getVisibleMembers(FIELDS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -27,12 +27,15 @@
 
 import java.text.MessageFormat;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementFilter;
 
+import com.sun.source.doctree.DocCommentTree;
 import com.sun.source.doctree.DocTree;
 import com.sun.source.doctree.DocTree.Kind;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
@@ -42,9 +45,11 @@
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
+
 /**
  * Builds the member summary.
  * There are two anonymous subtype variants of this builder, created
@@ -69,12 +74,9 @@
     /**
      * The member summary writers for the given class.
      */
-    private final EnumMap<VisibleMemberMap.Kind, MemberSummaryWriter> memberSummaryWriters;
+    private final EnumMap<VisibleMemberTable.Kind, MemberSummaryWriter> memberSummaryWriters;
 
-    /**
-     * The type being documented.
-     */
-    protected final TypeElement typeElement;
+    final PropertyHelper pHelper;
 
     /**
      * Construct a new MemberSummaryBuilder.
@@ -83,11 +85,10 @@
      * @param typeElement   the type element.
      */
     private MemberSummaryBuilder(Context context, TypeElement typeElement) {
-        super(context);
-        this.typeElement = typeElement;
-        memberSummaryWriters = new EnumMap<>(VisibleMemberMap.Kind.class);
-
-        comparator = utils.makeGeneralPurposeComparator();
+        super(context, typeElement);
+        memberSummaryWriters = new EnumMap<>(VisibleMemberTable.Kind.class);
+        comparator = utils.makeIndexUseComparator();
+        pHelper = new PropertyHelper(this);
     }
 
     /**
@@ -113,20 +114,14 @@
 
             @Override
             public boolean hasMembersToDocument() {
-                for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-                    VisibleMemberMap members = getVisibleMemberMap(kind);
-                    if (!members.noVisibleMembers()) {
-                        return true;
-                    }
-                }
-                return false;
+                return visibleMemberTable.hasVisibleMembers();
             }
         };
         WriterFactory wf = context.configuration.getWriterFactory();
-        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
-                    ? null
-                    : wf.getMemberSummaryWriter(classWriter, kind);
+        for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+            MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+                    ? wf.getMemberSummaryWriter(classWriter, kind)
+                    : null;
             builder.memberSummaryWriters.put(kind, msw);
         }
         return builder;
@@ -157,10 +152,10 @@
             }
         };
         WriterFactory wf = context.configuration.getWriterFactory();
-        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
-                    ? null
-                    : wf.getMemberSummaryWriter(annotationTypeWriter, kind);
+        for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+            MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+                    ? wf.getMemberSummaryWriter(annotationTypeWriter, kind)
+                    : null;
             builder.memberSummaryWriters.put(kind, msw);
         }
         return builder;
@@ -169,13 +164,12 @@
     /**
      * Return the specified visible member map.
      *
-     * @param kind the kind of visible member map to return.
      * @return the specified visible member map.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind kind) {
-        return configuration.getVisibleMemberMap(typeElement, kind);
+    public VisibleMemberTable getVisibleMemberTable() {
+        return visibleMemberTable;
     }
 
     /**.
@@ -184,9 +178,9 @@
      * @param kind the kind of member summary writer to return.
      * @return the specified member summary writer.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind kind) {
+    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberTable.Kind kind) {
         return memberSummaryWriters.get(kind);
     }
 
@@ -197,25 +191,31 @@
      *
      * @param kind the kind of elements to return.
      * @return a list of methods that will be documented.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public SortedSet<Element> members(VisibleMemberMap.Kind kind) {
+    public SortedSet<Element> members(VisibleMemberTable.Kind kind) {
         TreeSet<Element> out = new TreeSet<>(comparator);
-        out.addAll(getVisibleMemberMap(kind).getLeafMembers());
+        out.addAll(getVisibleMembers(kind));
         return out;
     }
 
     /**
+     * Returns true if there are members of the given kind, false otherwise.
+     * @param kind
+     * @return true if there are members of the given kind, false otherwise
+     */
+    public boolean hasMembers(VisibleMemberTable.Kind kind) {
+        return !getVisibleMembers(kind).isEmpty();
+    }
+
+    /**
      * Build the summary for the enum constants.
      *
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildEnumConstantsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ENUM_CONSTANTS);
+        addSummary(writer, ENUM_CONSTANTS, false, memberSummaryTree);
     }
 
     /**
@@ -224,11 +224,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeFieldsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_FIELDS);
+        addSummary(writer, ANNOTATION_TYPE_FIELDS, false, memberSummaryTree);
     }
 
     /**
@@ -237,11 +234,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeOptionalMemberSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_OPTIONAL);
+        addSummary(writer, ANNOTATION_TYPE_MEMBER_OPTIONAL, false, memberSummaryTree);
     }
 
     /**
@@ -250,11 +244,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeRequiredMemberSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_REQUIRED);
+        addSummary(writer, ANNOTATION_TYPE_MEMBER_REQUIRED, false, memberSummaryTree);
     }
 
     /**
@@ -263,11 +254,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildFieldsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.FIELDS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.FIELDS);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(FIELDS);
+        addSummary(writer, FIELDS, true, memberSummaryTree);
     }
 
     /**
@@ -276,11 +264,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildPropertiesSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.PROPERTIES);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.PROPERTIES);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(PROPERTIES);
+        addSummary(writer, PROPERTIES, true, memberSummaryTree);
     }
 
     /**
@@ -289,11 +274,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildNestedClassesSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.INNER_CLASSES);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.INNER_CLASSES);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(INNER_CLASSES);
+        addSummary(writer, INNER_CLASSES, true, memberSummaryTree);
     }
 
     /**
@@ -302,11 +284,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildMethodsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.METHODS);
-        VisibleMemberMap visibleMemberMap =
-               getVisibleMemberMap(VisibleMemberMap.Kind.METHODS);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(METHODS);
+        addSummary(writer, METHODS, true, memberSummaryTree);
     }
 
     /**
@@ -315,28 +294,25 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildConstructorsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.CONSTRUCTORS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.CONSTRUCTORS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(CONSTRUCTORS);
+        addSummary(writer, CONSTRUCTORS, false, memberSummaryTree);
     }
 
     /**
      * Build the member summary for the given members.
      *
      * @param writer the summary writer to write the output.
-     * @param visibleMemberMap the given members to summarize.
+     * @param kind the kind of  members to summarize.
      * @param summaryTreeList list of content trees to which the documentation will be added
      */
     private void buildSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
-        SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
+            VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+        SortedSet<? extends Element> members = asSortedSet(getVisibleMembers(kind));
         if (!members.isEmpty()) {
             for (Element member : members) {
-                final Element property = visibleMemberMap.getPropertyElement(member);
+                final Element property = pHelper.getPropertyElement(member);
                 if (property != null) {
-                    processProperty(visibleMemberMap, member, property);
+                    processProperty(member, property);
                 }
                 List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
                 if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
@@ -367,12 +343,10 @@
      * the see tags if the appropriate property getter and setter are
      * available.
      *
-     * @param visibleMemberMap the members information.
      * @param member the member which is to be augmented.
      * @param property the original property documentation.
      */
-    private void processProperty(VisibleMemberMap visibleMemberMap,
-                                 Element member,
+    private void processProperty(Element member,
                                  Element property) {
         CommentUtils cmtutils = configuration.cmtUtils;
         final boolean isSetter = isSetter(member);
@@ -418,8 +392,8 @@
 
         //add @see tags
         if (!isGetter && !isSetter) {
-            ExecutableElement getter = (ExecutableElement) visibleMemberMap.getGetterForProperty(member);
-            ExecutableElement setter = (ExecutableElement) visibleMemberMap.getSetterForProperty(member);
+            ExecutableElement getter = pHelper.getGetterForProperty((ExecutableElement)member);
+            ExecutableElement setter = pHelper.getSetterForProperty((ExecutableElement)member);
 
             if (null != getter) {
                 StringBuilder sb = new StringBuilder("#");
@@ -465,47 +439,28 @@
      * Build the inherited member summary for the given methods.
      *
      * @param writer the writer for this member summary.
-     * @param visibleMemberMap the map for the members to document.
+     * @param kind the kind of members to document.
      * @param summaryTreeList list of content trees to which the documentation will be added
      */
     private void buildInheritedSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
-        for (TypeElement inheritedClass : visibleMemberMap.getVisibleClasses()) {
+            VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+        VisibleMemberTable visibleMemberTable = getVisibleMemberTable();
+        SortedSet<? extends Element> inheritedMembersFromMap = asSortedSet(visibleMemberTable.getAllVisibleMembers(kind));
+
+        for (TypeElement inheritedClass : visibleMemberTable.getVisibleTypeElements()) {
             if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
                 continue;
             }
             if (inheritedClass == typeElement) {
                 continue;
             }
-            SortedSet<Element> inheritedMembersFromMap = asSortedSet(
-                    visibleMemberMap.getMembers(inheritedClass));
 
-            if (!inheritedMembersFromMap.isEmpty()) {
+            List<Element> members = inheritedMembersFromMap.stream()
+                    .filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)
+                    .collect(Collectors.toList());
+            if (!members.isEmpty()) {
                 SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
-                List<ExecutableElement> enclosedSuperMethods = utils.getMethods(inheritedClass);
-                for (Element inheritedMember : inheritedMembersFromMap) {
-                    if (visibleMemberMap.kind != VisibleMemberMap.Kind.METHODS) {
-                        inheritedMembers.add(inheritedMember);
-                        continue;
-                    }
-
-                    // Skip static methods in interfaces they are not inherited
-                    if (utils.isInterface(inheritedClass) && utils.isStatic(inheritedMember))
-                        continue;
-
-                    // If applicable, filter those overridden methods that
-                    // should not be documented in the summary/detail sections,
-                    // and instead document them in the footnote. Care must be taken
-                    // to handle JavaFX property methods, which have no source comments,
-                    // but comments for these are synthesized on the output.
-                    ExecutableElement inheritedMethod = (ExecutableElement)inheritedMember;
-                    if (enclosedSuperMethods.stream()
-                            .anyMatch(e -> utils.executableMembersEqual(inheritedMethod, e) &&
-                                    (!utils.isSimpleOverride(e) || visibleMemberMap.getPropertyElement(e) != null))) {
-                        inheritedMembers.add(inheritedMember);
-                    }
-                }
-
+                inheritedMembers.addAll(members);
                 Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
                 Content linksTree = writer.getInheritedSummaryLinksTree();
                 addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
@@ -529,17 +484,17 @@
      * Add the summary for the documentation.
      *
      * @param writer the writer for this member summary.
-     * @param visibleMemberMap the map for the members to document.
+     * @param kind the kind of members to document.
      * @param showInheritedSummary true if inherited summary should be documented
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     private void addSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
+            VisibleMemberTable.Kind kind, boolean showInheritedSummary,
             Content memberSummaryTree) {
         LinkedList<Content> summaryTreeList = new LinkedList<>();
-        buildSummary(writer, visibleMemberMap, summaryTreeList);
+        buildSummary(writer, kind, summaryTreeList);
         if (showInheritedSummary)
-            buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
+            buildInheritedSummary(writer, kind, summaryTreeList);
         if (!summaryTreeList.isEmpty()) {
             Content memberTree = writer.getMemberSummaryHeader(typeElement, memberSummaryTree);
             summaryTreeList.stream().forEach(memberTree::addContent);
@@ -547,9 +502,91 @@
         }
     }
 
-    private SortedSet<Element> asSortedSet(Collection<Element> members) {
+    private SortedSet<? extends Element> asSortedSet(Collection<? extends Element> members) {
         SortedSet<Element> out = new TreeSet<>(comparator);
         out.addAll(members);
         return out;
     }
+
+    static class PropertyHelper {
+
+        private final Map<Element, Element> classPropertiesMap = new HashMap<>();
+
+        private final MemberSummaryBuilder  builder;
+
+        PropertyHelper(MemberSummaryBuilder builder) {
+            this.builder = builder;
+            computeProperties();
+        }
+
+        private void computeProperties() {
+            VisibleMemberTable vmt = builder.getVisibleMemberTable();
+            List<ExecutableElement> props = ElementFilter.methodsIn(vmt.getVisibleMembers(PROPERTIES));
+            for (ExecutableElement propertyMethod : props) {
+                ExecutableElement getter = vmt.getPropertyGetter(propertyMethod);
+                ExecutableElement setter = vmt.getPropertySetter(propertyMethod);
+                VariableElement field = vmt.getPropertyField(propertyMethod);
+
+                addToPropertiesMap(propertyMethod, field, getter, setter);
+            }
+        }
+
+        private void addToPropertiesMap(ExecutableElement propertyMethod,
+                                        VariableElement field,
+                                        ExecutableElement getter,
+                                        ExecutableElement setter) {
+            if (field == null || builder.utils.getDocCommentTree(field) == null) {
+                addToPropertiesMap(propertyMethod, propertyMethod);
+                addToPropertiesMap(getter, propertyMethod);
+                addToPropertiesMap(setter, propertyMethod);
+            } else {
+                addToPropertiesMap(propertyMethod, field);
+                addToPropertiesMap(getter, field);
+                addToPropertiesMap(setter, field);
+            }
+        }
+
+        private void addToPropertiesMap(Element propertyMethod,
+                                        Element commentSource) {
+            if (null == propertyMethod || null == commentSource) {
+                return;
+            }
+            DocCommentTree docTree = builder.utils.getDocCommentTree(propertyMethod);
+
+            /* The second condition is required for the property buckets. In
+             * this case the comment is at the property method (not at the field)
+             * and it needs to be listed in the map.
+             */
+            if ((docTree == null) || propertyMethod.equals(commentSource)) {
+                classPropertiesMap.put(propertyMethod, commentSource);
+            }
+        }
+
+        /**
+         * Returns the property field documentation belonging to the given member.
+         * @param element the member for which the property documentation is needed.
+         * @return the property field documentation, null if there is none.
+         */
+        public Element getPropertyElement(Element element) {
+            return classPropertiesMap.get(element);
+        }
+
+        /**
+         * Returns the getter documentation belonging to the given property method.
+         * @param propertyMethod the method for which the getter is needed.
+         * @return the getter documentation, null if there is none.
+         */
+        public ExecutableElement getGetterForProperty(ExecutableElement propertyMethod) {
+            return builder.getVisibleMemberTable().getPropertyGetter(propertyMethod);
+        }
+
+        /**
+         * Returns the setter documentation belonging to the given property method.
+         * @param propertyMethod the method for which the setter is needed.
+         * @return the setter documentation, null if there is none.
+         */
+        public ExecutableElement getSetterForProperty(ExecutableElement propertyMethod) {
+            return builder.getVisibleMemberTable().getPropertySetter(propertyMethod);
+        }
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -37,8 +37,8 @@
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a method.
@@ -60,16 +60,6 @@
     private ExecutableElement currentMethod;
 
     /**
-     * The class whose methods are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible methods for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the method documentation.
      */
     private final MethodWriter writer;
@@ -77,7 +67,7 @@
     /**
      * The methods being documented.
      */
-    private final List<Element> methods;
+    private final List<? extends Element> methods;
 
 
     /**
@@ -90,12 +80,9 @@
     private MethodBuilder(Context context,
             TypeElement typeElement,
             MethodWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.METHODS);
-        methods = visibleMemberMap.getLeafMembers();
+        methods = getVisibleMembers(METHODS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -35,8 +35,9 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a property.
@@ -52,16 +53,6 @@
 public class PropertyBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose properties are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible properties for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the property documentation.
      */
     private final PropertyWriter writer;
@@ -69,7 +60,7 @@
     /**
      * The list of properties being documented.
      */
-    private final List<Element> properties;
+    private final List<? extends Element> properties;
 
     /**
      * The index of the current property that is being documented at this point
@@ -87,12 +78,9 @@
     private PropertyBuilder(Context context,
             TypeElement typeElement,
             PropertyWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.PROPERTIES);
-        properties = visibleMemberMap.getMembers(typeElement);
+        properties = getVisibleMembers(PROPERTIES);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Tue Apr 24 11:54:03 2018 -0700
@@ -84,7 +84,6 @@
 doclet.noInheritedDoc=@inheritDoc used but {0} does not override or implement any method.
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
-doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
 doclet.Requires_Summary=Requires
 doclet.Indirect_Requires_Summary=Indirect Requires
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties	Tue Apr 24 11:54:03 2018 -0700
@@ -75,7 +75,6 @@
 doclet.noInheritedDoc=@inheritDoc\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001{0}\u306F\u3069\u306E\u30E1\u30BD\u30C3\u30C9\u3082\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u5B9F\u88C5\u3057\u3066\u3044\u307E\u305B\u3093\u3002
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse={0}\u30BF\u30B0\u306F{1}\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u6B21\u306E\u30BF\u30A4\u30D7\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u306E\u307F\u3067\u3059: {2}\u3002
-doclet.javafx_tag_misuse=\u30BF\u30B0@propertyGetter\u3001@propertySetter\u304A\u3088\u3073@propertyDescription\u306F\u3001JavaFX\u306E\u30D7\u30ED\u30D1\u30C6\u30A3getter\u3068setter\u306E\u307F\u3067\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
 doclet.Package_Summary=\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981
 doclet.Requires_Summary=\u5FC5\u8981
 doclet.Indirect_Requires_Summary=\u9593\u63A5\u7684\u306B\u5FC5\u8981
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties	Tue Apr 24 11:54:03 2018 -0700
@@ -75,7 +75,6 @@
 doclet.noInheritedDoc=\u4F7F\u7528\u4E86 @inheritDoc, \u4F46{0}\u672A\u8986\u76D6\u6216\u5B9E\u73B0\u4EFB\u4F55\u65B9\u6CD5\u3002
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse=\u4E0D\u80FD\u5728{1}\u6587\u6863\u4E2D\u4F7F\u7528\u6807\u8BB0{0}\u3002\u53EA\u80FD\u5728\u4EE5\u4E0B\u7C7B\u578B\u7684\u6587\u6863\u4E2D\u4F7F\u7528\u8BE5\u6807\u8BB0: {2}\u3002
-doclet.javafx_tag_misuse=\u6807\u8BB0 @propertyGetter, @propertySetter \u548C @propertyDescription \u53EA\u80FD\u5728 JavaFX \u5C5E\u6027 getter \u548C setter \u4E2D\u4F7F\u7528\u3002
 doclet.Package_Summary=\u7A0B\u5E8F\u5305\u6982\u8981
 doclet.Requires_Summary=\u5FC5\u9700\u9879
 doclet.Indirect_Requires_Summary=\u95F4\u63A5\u5FC5\u9700\u9879
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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,7 +26,6 @@
 package jdk.javadoc.internal.doclets.toolkit.taglets;
 
 import java.io.*;
-import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -180,8 +179,7 @@
     private final boolean showauthor;
 
     /**
-     * True if we want to use JavaFX-related tags (@propertyGetter,
-     * @propertySetter, @propertyDescription, @defaultValue, @treatAsPrivate).
+     * True if we want to use JavaFX-related tags (@defaultValue, @treatAsPrivate).
      */
     private final boolean javafx;
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -161,7 +161,6 @@
      * have their own sub-class lists.
      *
      * @param classes all the classes in this run.
-     * @param configuration the current configuration of the doclet.
      */
     private void buildTree(Iterable<TypeElement> classes) {
         for (TypeElement aClass : classes) {
@@ -174,7 +173,7 @@
                 continue;
             }
 
-            if (utils.isHidden(aClass)) {
+            if (utils.hasHiddenTag(aClass)) {
                 continue;
             }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java	Tue Apr 24 11:54:03 2018 -0700
@@ -47,7 +47,8 @@
 
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Map all class uses for a given class.
@@ -243,8 +244,9 @@
                 mapExecutable(ctor);
             }
 
-            VisibleMemberMap vmm = configuration.getVisibleMemberMap(aClass, Kind.METHODS);
-            List<ExecutableElement> methods = ElementFilter.methodsIn(vmm.getMembers(aClass));
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(aClass);
+            List<ExecutableElement> methods = ElementFilter.methodsIn(vmt.getMembers(METHODS));
+
             for (ExecutableElement method : methods) {
                 mapExecutable(method);
                 mapTypeParameters(classToMethodTypeParam, method, method);
@@ -554,8 +556,8 @@
      * Map the AnnotationType to the members that use them as type parameters.
      *
      * @param map the map the insert the information into.
-     * @param element whose type parameters are being checked.
-     * @param holder the holder that owns the type parameters.
+     * @param e whose type parameters are being checked.
+     * @param holder owning the type parameters.
      */
     private <T extends Element> void mapAnnotations(final Map<TypeElement, List<T>> map,
             Element e, final T holder) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -276,9 +276,10 @@
             //NOTE:  When we fix the bug where ClassDoc.interfaceTypes() does
             //       not pass all implemented interfaces, we will use the
             //       appropriate element here.
-            ImplementedMethods implMethods
-                    = new ImplementedMethods((ExecutableElement) input.element, configuration);
-            List<ExecutableElement> implementedMethods = implMethods.build();
+            TypeElement encl = utils.getEnclosingTypeElement(input.element);
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(encl);
+            List<ExecutableElement> implementedMethods =
+                    vmt.getImplementedMethods((ExecutableElement)input.element);
             for (ExecutableElement implementedMethod : implementedMethods) {
                 inheritedSearchInput.element = implementedMethod;
                 output = search(configuration, inheritedSearchInput);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ImplementedMethods.java	Tue Apr 24 16:48:29 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, 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 jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-
-/**
- * For a given class method, build an array of interface methods which it
- * implements.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- */
-public class ImplementedMethods {
-
-    private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
-    private final List<ExecutableElement> methlist = new ArrayList<>();
-    private final Utils utils;
-    private final TypeElement typeElement;
-    private final ExecutableElement method;
-
-    public ImplementedMethods(ExecutableElement method, BaseConfiguration configuration) {
-        this.method = method;
-        this.utils = configuration.utils;
-        typeElement = utils.getEnclosingTypeElement(method);
-    }
-
-    /**
-     * Return the array of interface methods which the method passed in the
-     * constructor is implementing. The search/build order is as follows:
-     * <pre>
-     * 1. Search in all the immediate interfaces which this method's class is
-     *    implementing. Do it recursively for the superinterfaces as well.
-     * 2. Traverse all the superclasses and search recursively in the
-     *    interfaces which those superclasses implement.
-     *</pre>
-     *
-     * @return SortedSet<ExecutableElement> of implemented methods.
-     */
-    public List<ExecutableElement> build() {
-        buildImplementedMethodList();
-        return methlist;
-    }
-
-    public TypeMirror getMethodHolder(ExecutableElement ee) {
-        return interfaces.get(ee);
-    }
-
-    /**
-     * Search for the method in the array of interfaces. If found check if it is
-     * overridden by any other subinterface method which this class
-     * implements. If it is not overidden, add it in the method list.
-     * Do this recursively for all the extended interfaces for each interface
-     * from the array passed.
-     */
-    private void buildImplementedMethodList() {
-        Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
-        for (TypeMirror interfaceType : intfacs) {
-            ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
-            if (found != null) {
-                removeOverriddenMethod(found);
-                if (!overridingMethodFound(found)) {
-                    methlist.add(found);
-                    interfaces.put(found, interfaceType);
-                }
-            }
-        }
-    }
-
-    /**
-     * Search in the method list and check if it contains a method which
-     * is overridden by the method as parameter.  If found, remove the
-     * overridden method from the method list.
-     *
-     * @param method Is this method overriding a method in the method list.
-     */
-    private void removeOverriddenMethod(ExecutableElement method) {
-        TypeElement overriddenClass = utils.overriddenClass(method);
-        if (overriddenClass != null) {
-            for (int i = 0; i < methlist.size(); i++) {
-                TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
-                if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
-                    methlist.remove(i);  // remove overridden method
-                    return;
-                }
-            }
-        }
-    }
-
-    /**
-     * Search in the already found methods' list and check if it contains
-     * a method which is overriding the method parameter or is the method
-     * parameter itself.
-     *
-     * @param method MethodDoc Method to be searched in the Method List for
-     * an overriding method.
-     */
-    private boolean overridingMethodFound(ExecutableElement method) {
-        TypeElement containingClass = utils.getEnclosingTypeElement(method);
-        for (ExecutableElement listmethod : methlist) {
-            if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
-                // it's the same method.
-                return true;
-            }
-            TypeElement te = utils.overriddenClass(listmethod);
-            if (te == null) {
-                continue;
-            }
-            if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -35,7 +35,8 @@
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Messages;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Build the mapping of each Unicode character with it's member lists
@@ -165,8 +166,8 @@
     protected void putMembersInIndexMap(TypeElement te) {
         adjustIndexMap(utils.getAnnotationFields(te));
         adjustIndexMap(utils.getFields(te));
-        VisibleMemberMap vmm = configuration.getVisibleMemberMap(te, Kind.METHODS);
-        adjustIndexMap(vmm.getMembers(te));
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+        adjustIndexMap(vmt.getMembers(METHODS));
         adjustIndexMap(utils.getConstructors(te));
         adjustIndexMap(utils.getEnumConstants(te));
     }
@@ -216,7 +217,7 @@
      * Should this element be added to the index map?
      */
     protected boolean shouldAddToIndexMap(Element element) {
-        if (utils.isHidden(element)) {
+        if (utils.hasHiddenTag(element)) {
             return false;
         }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Tue Apr 24 11:54:03 2018 -0700
@@ -74,12 +74,10 @@
 import com.sun.source.doctree.DocTree.Kind;
 import com.sun.source.doctree.ParamTree;
 import com.sun.source.doctree.SerialFieldTree;
-import com.sun.source.doctree.StartElementTree;
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.LineMap;
 import com.sun.source.util.DocSourcePositions;
 import com.sun.source.util.DocTrees;
-import com.sun.source.util.SimpleDocTreeVisitor;
 import com.sun.source.util.TreePath;
 import com.sun.tools.javac.model.JavacTypes;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
@@ -95,7 +93,6 @@
 import static com.sun.source.doctree.DocTree.Kind.*;
 import static jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.MAX_CONSTANT_VALUE_INDEX_LENGTH;
 
-
 /**
  * Utilities Class for Doclets.
  *
@@ -806,9 +803,8 @@
             if (te == null) {
                 return null;
             }
-            VisibleMemberMap vmm = configuration.getVisibleMemberMap(te,
-                    VisibleMemberMap.Kind.METHODS);
-            for (Element e : vmm.getMembers(te)) {
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+            for (Element e : vmt.getMembers(VisibleMemberTable.Kind.METHODS)) {
                 ExecutableElement ee = (ExecutableElement)e;
                 if (configuration.workArounds.overrides(method, ee, origin) &&
                         !isSimpleOverride(ee)) {
@@ -1167,7 +1163,7 @@
         }
         TypeElement superClass = asTypeElement(superType);
         // skip "hidden" classes
-        while ((superClass != null && isHidden(superClass))
+        while ((superClass != null && hasHiddenTag(superClass))
                 || (superClass != null &&  !isPublic(superClass) && !isLinkable(superClass))) {
             TypeMirror supersuperType = superClass.getSuperclass();
             TypeElement supersuperClass = asTypeElement(supersuperType);
@@ -1416,7 +1412,7 @@
      * @param e the queried element
      * @return true if it exists, false otherwise
      */
-    public boolean isHidden(Element e) {
+    public boolean hasHiddenTag(Element e) {
         // prevent needless tests on elements which are not included
         if (!isIncluded(e)) {
             return false;
@@ -1462,14 +1458,14 @@
                 new TreeSet<>(makeGeneralPurposeComparator());
         if (!javafx) {
             for (Element te : classlist) {
-                if (!isHidden(te)) {
+                if (!hasHiddenTag(te)) {
                     filteredOutClasses.add((TypeElement)te);
                 }
             }
             return filteredOutClasses;
         }
         for (Element e : classlist) {
-            if (isPrivate(e) || isPackagePrivate(e) || isHidden(e)) {
+            if (isPrivate(e) || isPackagePrivate(e) || hasHiddenTag(e)) {
                 continue;
             }
             filteredOutClasses.add((TypeElement)e);
@@ -2246,18 +2242,6 @@
         return convertToTypeElement(getItems(e, false, INTERFACE));
     }
 
-    List<Element> getNestedClasses(TypeElement e) {
-        List<Element> result = new ArrayList<>();
-        recursiveGetItems(result, e, true, CLASS);
-        return result;
-    }
-
-    List<Element> getNestedClassesUnfiltered(TypeElement e) {
-        List<Element> result = new ArrayList<>();
-        recursiveGetItems(result, e, false, CLASS);
-        return result;
-    }
-
     public List<Element> getEnumConstants(Element e) {
         return getItems(e, true, ENUM_CONSTANT);
     }
@@ -2381,7 +2365,6 @@
     }
 
     EnumSet<ElementKind> nestedKinds = EnumSet.of(ANNOTATION_TYPE, CLASS, ENUM, INTERFACE);
-
     void recursiveGetItems(Collection<Element> list, Element e, boolean filter, ElementKind... select) {
         list.addAll(getItems0(e, filter, select));
         List<Element> classes = getItems0(e, filter, nestedKinds);
@@ -2411,7 +2394,8 @@
     }
 
     private SimpleElementVisitor9<Boolean, Void> shouldDocumentVisitor = null;
-    private boolean shouldDocument(Element e) {
+
+    protected boolean shouldDocument(Element e) {
         if (shouldDocumentVisitor == null) {
             shouldDocumentVisitor = new SimpleElementVisitor9<Boolean, Void>() {
                 private boolean hasSource(TypeElement e) {
@@ -2422,6 +2406,10 @@
                 // handle types
                 @Override
                 public Boolean visitType(TypeElement e, Void p) {
+                    // treat inner classes etc as members
+                    if (e.getNestingKind().isNested()) {
+                        return defaultAction(e, p);
+                    }
                     return configuration.docEnv.isSelected(e) && hasSource(e);
                 }
 
@@ -3273,5 +3261,11 @@
             this.first = first;
             this.second = second;
         }
+
+        public String toString() {
+            StringBuffer out = new StringBuffer();
+            out.append(first + ":" + second);
+            return out.toString();
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberCache.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit.util;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * This class manages the visible member table for each type element.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+
+public class VisibleMemberCache {
+    private final Map<TypeElement, VisibleMemberTable> cache;
+    private final BaseConfiguration configuration;
+
+    public VisibleMemberCache(BaseConfiguration configuration) {
+        this.configuration = configuration;
+        cache = new HashMap<>();
+    }
+
+    public VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+        return cache.computeIfAbsent(te, t -> new VisibleMemberTable(t, configuration, this));
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java	Tue Apr 24 16:48:29 2018 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,842 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, 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 jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-import java.util.regex.Pattern;
-
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-import com.sun.source.doctree.DocCommentTree;
-import com.sun.source.doctree.DocTree;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.Messages;
-
-/**
- * A data structure that encapsulates the visible members of a particular
- * type for a given class tree.  To use this data structure, you must specify
- * the type of member you are interested in (nested class, field, constructor
- * or method) and the leaf of the class tree.  The data structure will map
- * all visible members in the leaf and classes above the leaf in the tree.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Jamie Ho (rewrite)
- */
-public class VisibleMemberMap {
-
-    private boolean noVisibleMembers = true;
-
-    public static enum Kind {
-        INNER_CLASSES,
-        ENUM_CONSTANTS,
-        FIELDS,
-        CONSTRUCTORS,
-        METHODS,
-        ANNOTATION_TYPE_FIELDS,
-        ANNOTATION_TYPE_MEMBER_OPTIONAL,
-        ANNOTATION_TYPE_MEMBER_REQUIRED,
-        PROPERTIES;
-
-        public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
-        public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
-        public static String getNavLinkLabels(Kind kind) {
-            switch (kind) {
-                case INNER_CLASSES:
-                    return "doclet.navNested";
-                case ENUM_CONSTANTS:
-                    return "doclet.navEnum";
-                case FIELDS:
-                    return "doclet.navField";
-                case CONSTRUCTORS:
-                    return "doclet.navConstructor";
-                case METHODS:
-                    return "doclet.navMethod";
-                default:
-                    throw new AssertionError("unknown kind:" + kind);
-            }
-        }
-    }
-
-    public static final String STARTLEVEL = "start";
-
-    // properties aren't named setA* or getA*
-    private static final Pattern GETTERSETTERPATTERN = Pattern.compile("[sg]et\\p{Upper}.*");
-    /**
-     * List of TypeElement objects for which ClassMembers objects are built.
-     */
-    private final Set<TypeElement> visibleClasses;
-
-    /**
-     * Map for each member name on to a map which contains members with same
-     * name-signature. The mapped map will contain mapping for each MemberDoc
-     * onto it's respecive level string.
-     */
-    private final Map<Object, Map<Element, String>> memberNameMap = new HashMap<>();
-
-    /**
-     * Map of class and it's ClassMembers object.
-     */
-    private final Map<TypeElement, ClassMembers> classMap = new HashMap<>();
-
-    /**
-     * Type whose visible members are requested.  This is the leaf of
-     * the class tree being mapped.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * Member kind: InnerClasses/Fields/Methods?
-     */
-    public final Kind kind;
-
-    /**
-     * The configuration this VisibleMemberMap was created with.
-     */
-    private final BaseConfiguration configuration;
-    private final Messages messages;
-    private final Utils utils;
-    private final Comparator<Element> comparator;
-
-    private final Map<TypeElement, List<Element>> propertiesCache;
-    private final Map<Element, Element> classPropertiesMap;
-    private final Map<Element, GetterSetter> getterSetterMap;
-
-    /**
-     * Construct a VisibleMemberMap of the given type for the given class.
-     *
-     * @param typeElement whose members are being mapped.
-     * @param kind the kind of member that is being mapped.
-     * @param configuration the configuration to use to construct this
-     * VisibleMemberMap. If the field configuration.nodeprecated is true the
-     * deprecated members are excluded from the map. If the field
-     * configuration.javafx is true the JavaFX features are used.
-     */
-    public VisibleMemberMap(TypeElement typeElement,
-                            Kind kind,
-                            BaseConfiguration configuration) {
-        this.typeElement = typeElement;
-        this.kind = kind;
-        this.configuration = configuration;
-        this.messages = configuration.getMessages();
-        this.utils = configuration.utils;
-        propertiesCache = configuration.propertiesCache;
-        classPropertiesMap = configuration.classPropertiesMap;
-        getterSetterMap = configuration.getterSetterMap;
-        comparator  = utils.makeGeneralPurposeComparator();
-        visibleClasses = new LinkedHashSet<>();
-        new ClassMembers(typeElement, STARTLEVEL).build();
-    }
-
-    /**
-     * Return the list of visible classes in this map.
-     *
-     * @return the list of visible classes in this map.
-     */
-    public SortedSet<TypeElement> getVisibleClasses() {
-        SortedSet<TypeElement> vClasses = new TreeSet<>(comparator);
-        vClasses.addAll(visibleClasses);
-        return vClasses;
-    }
-
-    /**
-     * Returns the first method where the given method is visible.
-     * @param e the method whose visible enclosing type is to be found.
-     * @return the method found or null
-     */
-    public ExecutableElement getVisibleMethod(ExecutableElement e) {
-        if (kind != Kind.METHODS || e.getKind() != ElementKind.METHOD) {
-            throw new AssertionError("incompatible member type or visible member map" + e);
-        }
-        // start with the current class
-        for (Element m : getMembers(typeElement)) {
-            ExecutableElement mthd = (ExecutableElement)m;
-            if (utils.executableMembersEqual(mthd, e)) {
-                return mthd;
-            }
-        }
-
-        for (TypeElement te : visibleClasses) {
-            if (te == typeElement)
-                continue;
-            for (Element m : getMembers(te)) {
-                ExecutableElement mthd = (ExecutableElement)m;
-                if (utils.executableMembersEqual(mthd, e)) {
-                    return mthd;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the property field documentation belonging to the given member.
-     * @param element the member for which the property documentation is needed.
-     * @return the property field documentation, null if there is none.
-     */
-    public Element getPropertyElement(Element element) {
-        return classPropertiesMap.get(element);
-    }
-
-    /**
-     * Returns the getter documentation belonging to the given property method.
-     * @param propertyMethod the method for which the getter is needed.
-     * @return the getter documentation, null if there is none.
-     */
-    public Element getGetterForProperty(Element propertyMethod) {
-        return getterSetterMap.get(propertyMethod).getGetter();
-    }
-
-    /**
-     * Returns the setter documentation belonging to the given property method.
-     * @param propertyMethod the method for which the setter is needed.
-     * @return the setter documentation, null if there is none.
-     */
-    public Element getSetterForProperty(Element propertyMethod) {
-        return getterSetterMap.get(propertyMethod).getSetter();
-    }
-
-    /**
-     * Return the package private members inherited by the class.  Only return
-     * if parent is package private and not documented.
-     *
-     * @return the package private members inherited by the class.
-     */
-    private List<Element> getInheritedPackagePrivateMethods() {
-        List<Element> results = new ArrayList<>();
-        for (TypeElement currentClass : visibleClasses) {
-            if (currentClass != typeElement &&
-                utils.isPackagePrivate(currentClass) &&
-                !utils.isLinkable(currentClass)) {
-                // Document these members in the child class because
-                // the parent is inaccessible.
-                results.addAll(classMap.get(currentClass).members);
-            }
-        }
-        return results;
-    }
-
-    /**
-     * Returns a list of visible enclosed members of the mapped type element.
-     *
-     * In the case of methods, the list may contain those methods that are
-     * extended with no specification changes as indicated by the existence
-     * of a sole &commat;inheritDoc or devoid of any API commments.
-     *
-     * This list may also contain appended members, inherited by inaccessible
-     * super types. These members are documented in the subtype when the
-     * super type is not documented.
-     *
-     * @return a list of visible enclosed members
-     */
-
-    public List<Element> getLeafMembers() {
-        List<Element> result = new ArrayList<>();
-        result.addAll(getMembers(typeElement));
-        result.addAll(getInheritedPackagePrivateMethods());
-        return result;
-    }
-
-    // Cache to improve performance
-    private HashMap<ExecutableElement, Boolean> overridenMethodCache = new HashMap<>();
-
-    private boolean hasOverridden(ExecutableElement method) {
-        return overridenMethodCache.computeIfAbsent(method, m -> hasOverriddenCompute(m));
-    }
-
-    private boolean hasOverriddenCompute(ExecutableElement method) {
-        if (kind != Kind.METHODS) {
-            throw new AssertionError("Unexpected kind: " + kind);
-        }
-        for (TypeElement t : visibleClasses) {
-            for (Element member : classMap.get(t).members) {
-                ExecutableElement inheritedMethod = (ExecutableElement)member;
-                if (utils.elementUtils.overrides(method, inheritedMethod, t)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a list of enclosed members for the given type.
-     *
-     * @param typeElement the given type
-     *
-     * @return a list of enclosed members
-     */
-    public List<Element> getMembers(TypeElement typeElement) {
-        List<Element> result = new ArrayList<>();
-        if (this.kind == Kind.METHODS) {
-            for (Element member : classMap.get(typeElement).members) {
-                ExecutableElement method = (ExecutableElement)member;
-                if (hasOverridden(method)) {
-                    if (!utils.isSimpleOverride(method)) {
-                        result.add(method);
-                    }
-                } else {
-                    result.add(method);
-                }
-            }
-        } else {
-            result.addAll(classMap.get(typeElement).members);
-        }
-        return result;
-    }
-
-    public boolean hasMembers(TypeElement typeElement) {
-        return !classMap.get(typeElement).members.isEmpty();
-    }
-
-    private void fillMemberLevelMap(List<? extends Element> list, String level) {
-        for (Element element : list) {
-            Object key = getMemberKey(element);
-            Map<Element, String> memberLevelMap = memberNameMap.get(key);
-            if (memberLevelMap == null) {
-                memberLevelMap = new HashMap<>();
-                memberNameMap.put(key, memberLevelMap);
-            }
-            memberLevelMap.put(element, level);
-        }
-    }
-
-    private void purgeMemberLevelMap(Iterable<? extends Element> list, String level) {
-        for (Element element : list) {
-            Object key = getMemberKey(element);
-            Map<Element, String> memberLevelMap = memberNameMap.get(key);
-            if (memberLevelMap != null && level.equals(memberLevelMap.get(element)))
-                memberLevelMap.remove(element);
-        }
-    }
-
-    /**
-     * Represents a class member.
-     */
-    private class ClassMember {
-        private Set<Element> members;
-
-        public ClassMember(Element element) {
-            members = new HashSet<>();
-            members.add(element);
-        }
-
-        public boolean isEqual(ExecutableElement method) {
-            for (Element member : members) {
-                if (member.getKind() != ElementKind.METHOD)
-                    continue;
-                ExecutableElement thatMethod = (ExecutableElement) member;
-                if (utils.executableMembersEqual(method, thatMethod) &&
-                        !utils.isSimpleOverride(thatMethod)) {
-                    members.add(method);
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * A data structure that represents the class members for
-     * a visible class.
-     */
-    private class ClassMembers {
-
-        /**
-         * The mapping class, whose inherited members are put in the
-         * {@link #members} list.
-         */
-        private final TypeElement typeElement;
-
-        /**
-         * List of members from the mapping class.
-         */
-        private List<Element> members = null;
-
-        /**
-         * Level/Depth of inheritance.
-         */
-        private final String level;
-
-        private ClassMembers(TypeElement mappingClass, String level) {
-            this.typeElement = mappingClass;
-            this.level = level;
-            if (classMap.containsKey(mappingClass) &&
-                        level.startsWith(classMap.get(mappingClass).level)) {
-                //Remove lower level class so that it can be replaced with
-                //same class found at higher level.
-                purgeMemberLevelMap(getClassMembers(mappingClass, false),
-                    classMap.get(mappingClass).level);
-                classMap.remove(mappingClass);
-                visibleClasses.remove(mappingClass);
-            }
-            if (!classMap.containsKey(mappingClass)) {
-                classMap.put(mappingClass, this);
-                visibleClasses.add(mappingClass);
-            }
-        }
-
-        private void build() {
-            if (kind == Kind.CONSTRUCTORS) {
-                addMembers(typeElement);
-            } else {
-                mapClass();
-            }
-        }
-
-        private void mapClass() {
-            addMembers(typeElement);
-            List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
-            for (TypeMirror anInterface : interfaces) {
-                String locallevel = level + 1;
-                ClassMembers cm = new ClassMembers(utils.asTypeElement(anInterface), locallevel);
-                cm.mapClass();
-            }
-            if (utils.isClass(typeElement)) {
-                TypeElement superclass = utils.getSuperClass(typeElement);
-                if (!(superclass == null || typeElement.equals(superclass))) {
-                    ClassMembers cm = new ClassMembers(superclass, level + "c");
-                    cm.mapClass();
-                }
-            }
-        }
-
-        /**
-         * Get all the valid members from the mapping class. Get the list of
-         * members for the class to be included into(ctii), also get the level
-         * string for ctii. If mapping class member is not already in the
-         * inherited member list and if it is visible in the ctii and not
-         * overridden, put such a member in the inherited member list.
-         * Adjust member-level-map, class-map.
-         */
-        private void addMembers(TypeElement fromClass) {
-            List<Element> result = new ArrayList<>();
-            for (Element element : getClassMembers(fromClass, true)) {
-                if (memberIsVisible(element)) {
-                    if (!isOverridden(element, level)) {
-                        if (!utils.isHidden(element)) {
-                            result.add(element);
-                        }
-                    }
-                }
-            }
-            if (members != null) {
-                throw new AssertionError("members should not be null");
-            }
-            members = Collections.unmodifiableList(result);
-            if (!members.isEmpty()) {
-                noVisibleMembers = false;
-            }
-            fillMemberLevelMap(getClassMembers(fromClass, false), level);
-        }
-
-        /**
-         * Is given element visible in given typeElement in terms of inheritance? The given element
-         * is visible in the given typeElement if it is public or protected and if it is
-         * package-private if it's containing class is in the same package as the given typeElement.
-         */
-        private boolean memberIsVisible(Element element) {
-            if (utils.getEnclosingTypeElement(element).equals(VisibleMemberMap.this.typeElement)) {
-                //Member is in class that we are finding visible members for.
-                //Of course it is visible.
-                return true;
-            } else if (utils.isPrivate(element)) {
-                //Member is in super class or implemented interface.
-                //Private, so not inherited.
-                return false;
-            } else if (utils.isPackagePrivate(element)) {
-                //Member is package private.  Only return true if its class is in
-                //same package.
-                return utils.containingPackage(element).equals(utils.containingPackage(VisibleMemberMap.this.typeElement));
-            } else {
-                //Public members are always inherited.
-                return true;
-            }
-        }
-
-        /**
-         * Return all available class members.
-         */
-        private List<? extends Element> getClassMembers(TypeElement te, boolean filter) {
-            if (utils.isEnum(te) && kind == Kind.CONSTRUCTORS) {
-                //If any of these rules are hit, return empty array because
-                //we don't document these members ever.
-                return Collections.emptyList();
-            }
-            List<? extends Element> list;
-            switch (kind) {
-                case ANNOTATION_TYPE_FIELDS:
-                    list = (filter)
-                            ? utils.getAnnotationFields(te)
-                            : utils.getAnnotationFieldsUnfiltered(te);
-                    break;
-                case ANNOTATION_TYPE_MEMBER_OPTIONAL:
-                    list = utils.isAnnotationType(te)
-                            ? filterAnnotations(te, false)
-                            : Collections.emptyList();
-                    break;
-                case ANNOTATION_TYPE_MEMBER_REQUIRED:
-                    list = utils.isAnnotationType(te)
-                            ? filterAnnotations(te, true)
-                            : Collections.emptyList();
-                    break;
-                case INNER_CLASSES:
-                    List<TypeElement> xlist = filter
-                            ? utils.getInnerClasses(te)
-                            : utils.getInnerClassesUnfiltered(te);
-                    list = new ArrayList<>(xlist);
-                    break;
-                case ENUM_CONSTANTS:
-                    list = utils.getEnumConstants(te);
-                    break;
-                case FIELDS:
-                    if (filter) {
-                        list = utils.isAnnotationType(te)
-                                ? utils.getAnnotationFields(te)
-                                : utils.getFields(te);
-                    } else {
-                        list = utils.isAnnotationType(te)
-                                ? utils.getAnnotationFieldsUnfiltered(te)
-                                : utils.getFieldsUnfiltered(te);
-                    }
-                    break;
-                case CONSTRUCTORS:
-                    list = utils.getConstructors(te);
-                    break;
-                case METHODS:
-                    list = filter ? utils.getMethods(te) : utils.getMethodsUnfiltered(te);
-                    checkOnPropertiesTags(list);
-                    break;
-                case PROPERTIES:
-                    list = properties(te, filter);
-                    break;
-                default:
-                    list = Collections.emptyList();
-            }
-            // Deprected members should be excluded or not?
-            if (configuration.nodeprecated) {
-                return utils.excludeDeprecatedMembers(list);
-            }
-            return list;
-        }
-
-        /**
-         * Filter the annotation type members and return either the required
-         * members or the optional members, depending on the value of the
-         * required parameter.
-         *
-         * @param typeElement The annotation type to process.
-         * @param required
-         * @return the annotation type members and return either the required
-         * members or the optional members, depending on the value of the
-         * required parameter.
-         */
-        private List<Element> filterAnnotations(TypeElement typeElement, boolean required) {
-            List<Element> members = utils.getAnnotationMethods(typeElement);
-            List<Element> targetMembers = new ArrayList<>();
-            for (Element member : members) {
-                ExecutableElement ee = (ExecutableElement)member;
-                if ((required && ee.getDefaultValue() == null)
-                        || ((!required) && ee.getDefaultValue() != null)) {
-                    targetMembers.add(member);
-                }
-            }
-            return targetMembers;
-        }
-
-        /**
-         * Is member overridden? The member is overridden if it is found in the
-         * same level hierarchy e.g. member at level "11" overrides member at
-         * level "111".
-         */
-        private boolean isOverridden(Element element, String level) {
-            Object key = getMemberKey(element);
-            Map<?, String> memberLevelMap = (Map<?, String>) memberNameMap.get(key);
-            if (memberLevelMap == null)
-                return false;
-            for (String mappedlevel : memberLevelMap.values()) {
-                if (mappedlevel.equals(STARTLEVEL)
-                        || (level.startsWith(mappedlevel)
-                        && !level.equals(mappedlevel))) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private List<Element> properties(final TypeElement typeElement, final boolean filter) {
-            final List<ExecutableElement> allMethods = filter
-                    ? utils.getMethods(typeElement)
-                    : utils.getMethodsUnfiltered(typeElement);
-            final List<VariableElement> allFields = utils.getFieldsUnfiltered(typeElement);
-
-            if (propertiesCache.containsKey(typeElement)) {
-                return propertiesCache.get(typeElement);
-            }
-
-            final List<Element> result = new ArrayList<>();
-
-            for (final Element propertyMethod : allMethods) {
-                ExecutableElement ee = (ExecutableElement)propertyMethod;
-                if (!isPropertyMethod(ee)) {
-                    continue;
-                }
-
-                final ExecutableElement getter = getterForField(allMethods, ee);
-                final ExecutableElement setter = setterForField(allMethods, ee);
-                final VariableElement field = fieldForProperty(allFields, ee);
-
-                addToPropertiesMap(setter, getter, ee, field);
-                getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter));
-                result.add(ee);
-            }
-            propertiesCache.put(typeElement, result);
-            return result;
-        }
-
-        private void addToPropertiesMap(ExecutableElement setter,
-                                        ExecutableElement getter,
-                                        ExecutableElement propertyMethod,
-                                        VariableElement field) {
-            if (field == null || utils.getDocCommentTree(field) == null) {
-                addToPropertiesMap(setter, propertyMethod);
-                addToPropertiesMap(getter, propertyMethod);
-                addToPropertiesMap(propertyMethod, propertyMethod);
-            } else {
-                addToPropertiesMap(getter, field);
-                addToPropertiesMap(setter, field);
-                addToPropertiesMap(propertyMethod, field);
-            }
-        }
-
-        private void addToPropertiesMap(Element propertyMethod,
-                                        Element commentSource) {
-            if (null == propertyMethod || null == commentSource) {
-                return;
-            }
-            DocCommentTree docTree = utils.getDocCommentTree(propertyMethod);
-
-            /* The second condition is required for the property buckets. In
-             * this case the comment is at the property method (not at the field)
-             * and it needs to be listed in the map.
-             */
-            if ((docTree == null) || propertyMethod.equals(commentSource)) {
-                classPropertiesMap.put(propertyMethod, commentSource);
-            }
-        }
-
-        private ExecutableElement getterForField(List<ExecutableElement> methods,
-                                         ExecutableElement propertyMethod) {
-            final String propertyMethodName = utils.getSimpleName(propertyMethod);
-            final String fieldName = propertyMethodName.substring(0,
-                            propertyMethodName.lastIndexOf("Property"));
-            final String fieldNameUppercased =
-                    "" + Character.toUpperCase(fieldName.charAt(0))
-                                            + fieldName.substring(1);
-            final String getterNamePattern;
-            final String fieldTypeName = propertyMethod.getReturnType().toString();
-            if ("boolean".equals(fieldTypeName)
-                    || fieldTypeName.endsWith("BooleanProperty")) {
-                getterNamePattern = "(is|get)" + fieldNameUppercased;
-            } else {
-                getterNamePattern = "get" + fieldNameUppercased;
-            }
-
-            for (ExecutableElement method : methods) {
-                if (Pattern.matches(getterNamePattern, utils.getSimpleName(method))) {
-                    if (method.getParameters().isEmpty() &&
-                            utils.isPublic(method) || utils.isProtected(method)) {
-                        return method;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private ExecutableElement setterForField(List<ExecutableElement> methods,
-                                         ExecutableElement propertyMethod) {
-            final String propertyMethodName = utils.getSimpleName(propertyMethod);
-            final String fieldName =
-                    propertyMethodName.substring(0,
-                            propertyMethodName.lastIndexOf("Property"));
-            final String fieldNameUppercased =
-                    "" + Character.toUpperCase(fieldName.charAt(0))
-                                             + fieldName.substring(1);
-            final String setter = "set" + fieldNameUppercased;
-
-            for (ExecutableElement method : methods) {
-                if (setter.equals(utils.getSimpleName(method))) {
-                    if (method.getParameters().size() == 1
-                            && method.getReturnType().getKind() == TypeKind.VOID
-                            && (utils.isPublic(method) || utils.isProtected(method))) {
-                        return method;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private VariableElement fieldForProperty(List<VariableElement> fields, ExecutableElement property) {
-
-            for (VariableElement field : fields) {
-                final String fieldName = utils.getSimpleName(field);
-                final String propertyName = fieldName + "Property";
-                if (propertyName.equals(utils.getSimpleName(property))) {
-                    return field;
-                }
-            }
-            return null;
-        }
-
-        private boolean isPropertyMethod(ExecutableElement method) {
-            if (!configuration.javafx) {
-               return false;
-            }
-            if (!utils.getSimpleName(method).endsWith("Property")) {
-                return false;
-            }
-
-            if (!memberIsVisible(method)) {
-                return false;
-            }
-
-            if (GETTERSETTERPATTERN.matcher(utils.getSimpleName(method)).matches()) {
-                return false;
-            }
-            if (!method.getTypeParameters().isEmpty()) {
-                return false;
-            }
-            return method.getParameters().isEmpty()
-                    && method.getReturnType().getKind() != TypeKind.VOID;
-        }
-
-        private void checkOnPropertiesTags(List<? extends Element> members) {
-            for (Element e: members) {
-                ExecutableElement ee = (ExecutableElement)e;
-                if (utils.isIncluded(ee)) {
-                    CommentHelper ch = utils.getCommentHelper(ee);
-                    for (DocTree tree: utils.getBlockTags(ee)) {
-                        String tagName = ch.getTagName(tree);
-                        if (tagName.equals("@propertySetter")
-                                || tagName.equals("@propertyGetter")
-                                || tagName.equals("@propertyDescription")) {
-                            if (!isPropertyGetterOrSetter(members, ee)) {
-                                messages.warning(ch.getDocTreePath(tree),
-                                        "doclet.javafx_tag_misuse");
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        private boolean isPropertyGetterOrSetter(List<? extends Element> members,
-                                                 ExecutableElement method) {
-            String propertyName = utils.propertyName(method);
-            if (!propertyName.isEmpty()) {
-                String propertyMethodName = propertyName + "Property";
-                for (Element member: members) {
-                    if (utils.getSimpleName(member).equals(propertyMethodName)) {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        }
-    }
-
-    public class GetterSetter {
-        private final Element getter;
-        private final Element setter;
-
-        public GetterSetter(Element getter, Element setter) {
-            this.getter = getter;
-            this.setter = setter;
-        }
-
-        public Element getGetter() {
-            return getter;
-        }
-
-        public Element getSetter() {
-            return setter;
-        }
-    }
-
-    /**
-     * Return true if this map has no visible members.
-     *
-     * @return true if this map has no visible members.
-     */
-    public boolean noVisibleMembers() {
-        return noVisibleMembers;
-    }
-
-    private ClassMember getClassMember(ExecutableElement member) {
-        for (Object key : memberNameMap.keySet()) {
-            if (key instanceof String) {
-                continue;
-            }
-            if (((ClassMember) key).isEqual(member)) {
-                return (ClassMember) key;
-            }
-        }
-        return new ClassMember(member);
-    }
-
-    /**
-     * Return the key to the member map for the given member.
-     */
-    private Object getMemberKey(Element element) {
-        if (utils.isConstructor(element)) {
-            return utils.getSimpleName(element) + utils.flatSignature((ExecutableElement)element);
-        } else if (utils.isMethod(element)) {
-            return getClassMember((ExecutableElement) element);
-        } else if (utils.isField(element) || utils.isEnumConstant(element) || utils.isAnnotationType(element)) {
-            return utils.getSimpleName(element);
-        } else { // it's a class or interface
-            String classOrIntName = utils.getSimpleName(element);
-            //Strip off the containing class name because we only want the member name.
-            classOrIntName = classOrIntName.indexOf('.') != 0
-                    ? classOrIntName.substring(classOrIntName.lastIndexOf('.'))
-                    : classOrIntName;
-            return "clint" + classOrIntName;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,992 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleElementVisitor9;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+import jdk.javadoc.internal.doclets.toolkit.PropertyUtils;
+
+/**
+ * This class computes the main data structure for the doclet's
+ * operations. Essentially, the implementation encapsulating the
+ * javax.lang.models view of what can be documented about a
+ * type element's members.
+ * <p>
+ * The general operations are as follows:
+ * <p>
+ * Members: these are the members from jx.l.m's view but
+ * are structured along the kinds of this class.
+ * <p>
+ * Extra Members: these are members enclosed in an undocumented
+ * package-private type element, and may not be linkable (or documented),
+ * however, the members of such a type element may be documented, as if
+ * declared in the sub type, only if the enclosing type is not being
+ * documented by a filter such as -public, -protected, etc.
+ * <p>
+ * Visible Members: these are the members that are "visible"
+ * and available and should be documented, in a type element.
+ * <p>
+ * The basic rule for computation: when considering a type element,
+ * besides its immediate direct types and interfaces, the computation
+ * should not expand to any other type in the inheritance hierarchy.
+ * <p>
+ * This table generates all the data structures it needs for each
+ * type, as its own view, and will present some form of this to the
+ * doclet as and when required to.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ *
+ */
+
+public class VisibleMemberTable {
+
+    public enum Kind {
+        INNER_CLASSES,
+        ENUM_CONSTANTS,
+        FIELDS,
+        CONSTRUCTORS,
+        METHODS,
+        ANNOTATION_TYPE_FIELDS,
+        ANNOTATION_TYPE_MEMBER_OPTIONAL,
+        ANNOTATION_TYPE_MEMBER_REQUIRED,
+        PROPERTIES;
+
+        public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
+        public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
+    }
+
+    final TypeElement te;
+    final TypeElement parent;
+
+    final BaseConfiguration config;
+    final Utils utils;
+    final VisibleMemberCache mcache;
+
+    private List<VisibleMemberTable> allSuperclasses;
+    private List<VisibleMemberTable> allSuperinterfaces;
+    private List<VisibleMemberTable> parents;
+
+
+    private Map<Kind, List<Element>> extraMembers = new EnumMap<>(Kind.class);
+    private Map<Kind, List<Element>> visibleMembers = null;
+    private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
+
+    // Keeps track of method overrides
+    Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
+            = new LinkedHashMap<>();
+
+    protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
+                                 VisibleMemberCache mcache) {
+        config = configuration;
+        utils = configuration.utils;
+        te = typeElement;
+        parent = utils.getSuperClass(te);
+        this.mcache = mcache;
+        allSuperclasses = new ArrayList<>();
+        allSuperinterfaces = new ArrayList<>();
+        parents = new ArrayList<>();
+    }
+
+    private synchronized void ensureInitialized() {
+        if (visibleMembers != null)
+            return;
+
+        visibleMembers = new EnumMap<>(Kind.class);
+        for (Kind kind : Kind.values()) {
+            visibleMembers.put(kind, new ArrayList<>());
+        }
+        computeParents();
+        computeVisibleMembers();
+    }
+
+    List<? extends Element> getExtraMembers(Kind kind) {
+        ensureInitialized();
+        return visibleMembers.getOrDefault(kind, Collections.emptyList());
+    }
+
+    List<VisibleMemberTable> getAllSuperclasses() {
+        ensureInitialized();
+        return allSuperclasses;
+    }
+
+    List<VisibleMemberTable> getAllSuperinterfaces() {
+        ensureInitialized();
+        return allSuperinterfaces;
+    }
+
+    /**
+     * Returns a list of all visible enclosed members of a type element,
+     * and inherited members.
+     * <p>
+     * Notes:
+     * a. The list may or may not contain simple overridden methods.
+     * A simple overridden method is one that overrides a super method
+     * with no specification changes as indicated by the existence of a
+     * sole &commat;inheritDoc or devoid of any API commments.
+     * <p>
+     * b.The list may contain (extra) members, inherited by inaccessible
+     * super types, primarily package private types. These members are
+     * required to be documented in the subtype when the super type is
+     * not documented.
+     *
+     * @param kind the member kind
+     * @return a list of all visible members
+     */
+    public List<? extends Element> getAllVisibleMembers(Kind kind) {
+        ensureInitialized();
+        return visibleMembers.getOrDefault(kind, Collections.emptyList());
+    }
+
+    /**
+     * Returns a list of visible enclosed members of a specified kind,
+     * filtered by the specified predicate.
+     * @param kind the member kind
+     * @param p the predicate used to filter the output
+     * @return a list of visible enclosed members
+     */
+    public List<? extends Element> getVisibleMembers(Kind kind, Predicate<Element> p) {
+        ensureInitialized();
+
+        return visibleMembers.getOrDefault(kind, Collections.emptyList()).stream()
+                .filter(p)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns a list of all enclosed members including any extra members.
+     * Typically called by various builders.
+     *
+     * @param kind the member kind
+     * @return a list of visible enclosed members
+     */
+    public List<? extends Element> getVisibleMembers(Kind kind) {
+        Predicate<Element> declaredAndLeafMembers = e -> {
+            TypeElement encl = utils.getEnclosingTypeElement(e);
+            return encl == te || isUndocumentedEnclosure(encl);
+        };
+        return getVisibleMembers(kind, declaredAndLeafMembers);
+    }
+
+    /**
+     * Returns a list of visible enclosed members of given kind,
+     * declared in this type element, and does not include
+     * any inherited members or extra members.
+     *
+     * @return a list of visible enclosed members in this type
+     */
+    public List<? extends Element> getMembers(Kind kind) {
+        Predicate<Element> onlyLocallyDeclaredMembers = e -> utils.getEnclosingTypeElement(e) == te;
+        return getVisibleMembers(kind, onlyLocallyDeclaredMembers);
+    }
+
+    /**
+     * Returns the overridden method, if it is simply overridding or the
+     * method is a member of a package private type, this method is
+     * primarily used to determine the location of a possible comment.
+     *
+     * @param e the method to check
+     * @return the method found or null
+     */
+    public ExecutableElement getOverriddenMethod(ExecutableElement e) {
+        ensureInitialized();
+
+        OverridingMethodInfo found = overriddenMethodTable.get(e);
+        if (found != null && (found.simpleOverride || isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) {
+            return found.overrider;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the simply overridden method.
+     * @param e the method to check
+     * @return the overridden method or null
+     */
+    public ExecutableElement getsimplyOverriddenMethod(ExecutableElement e) {
+        ensureInitialized();
+
+        OverridingMethodInfo found = overriddenMethodTable.get(e);
+        if (found != null && found.simpleOverride) {
+            return found.overrider;
+        }
+        return null;
+    }
+
+    /**
+     * Returns a set of visible type elements in this type element's lineage.
+     * <p>
+     * This method returns the super-types in the inheritance
+     * order C, B, A, j.l.O. The super-interfaces however are
+     * alpha sorted and appended to the resulting set.
+     *
+     * @return the list of visible classes in this map.
+     */
+    public Set<TypeElement> getVisibleTypeElements() {
+        ensureInitialized();
+        Set<TypeElement> result = new LinkedHashSet<>();
+
+        // Add this type element first.
+        result.add(te);
+
+        // Add the super classes.
+        allSuperclasses.stream()
+                .map(vmt -> vmt.te)
+                .forEach(result::add);
+
+        // ... and finally the sorted super interfaces.
+        allSuperinterfaces.stream()
+                .map(vmt -> vmt.te)
+                .sorted(utils.makeGeneralPurposeComparator())
+                .forEach(result::add);
+
+        return result;
+    }
+
+    /**
+     * Returns true if this table contains visible members.
+     *
+     * @return true if visible members are present.
+     */
+    public boolean hasVisibleMembers() {
+        for (Kind kind : Kind.values()) {
+            if (hasVisibleMembers(kind))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this table contains visible members of
+     * the specified kind, including inhertied members.
+     *
+     * @return true if visible members are present.
+     */
+    public boolean hasVisibleMembers(Kind kind) {
+        ensureInitialized();
+        List<Element> elements = visibleMembers.get(kind);
+        return elements != null && !elements.isEmpty();
+    }
+
+    /**
+     * Returns the property field associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the field or null if absent
+     */
+    public VariableElement getPropertyField(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.field;
+    }
+
+    /**
+     * Returns the getter method associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the getter or null if absent
+     */
+    public ExecutableElement getPropertyGetter(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.getter;
+    }
+
+    /**
+     * Returns the setter method associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the setter or null if absent
+     */
+    public ExecutableElement getPropertySetter(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.setter;
+    }
+
+    boolean isUndocumentedEnclosure(TypeElement encl) {
+        return utils.isPackagePrivate(encl) && !utils.isLinkable(encl);
+    }
+
+    private void computeParents() {
+        for (TypeMirror intfType : te.getInterfaces()) {
+            TypeElement intfc = utils.asTypeElement(intfType);
+            if (intfc != null) {
+                VisibleMemberTable vmt = mcache.getVisibleMemberTable(intfc);
+                allSuperinterfaces.add(vmt);
+                parents.add(vmt);
+                allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+            }
+        }
+
+        if (parent != null) {
+            VisibleMemberTable vmt = mcache.getVisibleMemberTable(parent);
+            allSuperclasses.add(vmt);
+            allSuperclasses.addAll(vmt.getAllSuperclasses());
+            // Add direct super interfaces of a super class, if any.
+            allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+            parents.add(vmt);
+        }
+    }
+
+    private void computeVisibleMembers() {
+
+        // Note: these have some baggage, and are redundant,
+        // allow this to be GC'ed.
+        LocalMemberTable lmt = new LocalMemberTable();
+
+        for (Kind k : Kind.values()) {
+            computeLeafMembers(lmt, k);
+            computeVisibleMembers(lmt, k);
+        }
+        // All members have been computed, compute properties.
+        computeVisibleProperties(lmt);
+    }
+
+    private void computeLeafMembers(LocalMemberTable lmt, Kind kind) {
+        List<Element> list = new ArrayList<>();
+        if (isUndocumentedEnclosure(te)) {
+            list.addAll(lmt.getOrderedMembers(kind));
+        }
+        parents.forEach(pvmt -> {
+            list.addAll(pvmt.getExtraMembers(kind));
+        });
+        extraMembers.put(kind, Collections.unmodifiableList(list));
+    }
+
+    void computeVisibleMembers(LocalMemberTable lmt, Kind kind) {
+        switch (kind) {
+            case FIELDS: case INNER_CLASSES:
+                computeVisibleFieldsAndInnerClasses(lmt, kind);
+                return;
+
+            case METHODS:
+                computeVisibleMethods(lmt);
+                return;
+
+            // Defer properties related computations for later.
+            case PROPERTIES:
+                return;
+
+            default:
+                List<Element> list = lmt.getOrderedMembers(kind).stream()
+                        .filter(this::mustDocument)
+                        .collect(Collectors.toList());
+                visibleMembers.put(kind, Collections.unmodifiableList(list));
+                break;
+        }
+    }
+
+    private boolean mustDocument(Element e) {
+        return !utils.hasHiddenTag(e) && utils.shouldDocument(e);
+    }
+
+    private boolean allowInheritedMembers(Element e, Kind kind, LocalMemberTable lmt) {
+        return isInherited(e) && !isMemberHidden(e, kind, lmt);
+    }
+
+    private boolean isInherited(Element e) {
+        if (utils.isPrivate(e))
+            return false;
+
+        if (utils.isPackagePrivate(e))
+            // Allowed iff this type-element is in the same package as the element
+            return utils.containingPackage(e).equals(utils.containingPackage(te));
+
+        return true;
+    }
+
+    private boolean isMemberHidden(Element inheritedMember, Kind kind, LocalMemberTable lmt) {
+        Elements elementUtils = config.docEnv.getElementUtils();
+        switch(kind) {
+            default:
+                List<Element> list = lmt.getMembers(inheritedMember, kind);
+                if (list.isEmpty())
+                    return false;
+                return elementUtils.hides(list.get(0), inheritedMember);
+            case METHODS: case CONSTRUCTORS: // Handled elsewhere.
+                throw new IllegalArgumentException("incorrect kind");
+        }
+    }
+
+    private void computeVisibleFieldsAndInnerClasses(LocalMemberTable lmt, Kind kind) {
+        Set<Element> result = new LinkedHashSet<>();
+        for (VisibleMemberTable pvmt : parents) {
+            result.addAll(pvmt.getExtraMembers(kind));
+            result.addAll(pvmt.getAllVisibleMembers(kind));
+        }
+
+        // Filter out members in the inherited list that are hidden
+        // by this type or should not be inherited at all.
+        List<Element> list = result.stream()
+                .filter(e -> allowInheritedMembers(e, kind, lmt)).collect(Collectors.toList());
+
+        // Prefix local results first
+        list.addAll(0, lmt.getOrderedMembers(kind));
+
+        // Filter out elements that should not be documented
+        list = list.stream()
+                .filter(this::mustDocument)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(kind, Collections.unmodifiableList(list));
+    }
+
+    private void computeVisibleMethods(LocalMemberTable lmt) {
+        Set<Element> inheritedMethods = new LinkedHashSet<>();
+        Map<ExecutableElement, List<ExecutableElement>> overriddenByTable = new HashMap<>();
+        for (VisibleMemberTable pvmt : parents) {
+            // Merge the lineage overrides into local table
+            pvmt.overriddenMethodTable.entrySet().forEach(e -> {
+                OverridingMethodInfo p = e.getValue();
+                if (!p.simpleOverride) { // consider only real overrides
+                    List<ExecutableElement> list = overriddenByTable.computeIfAbsent(p.overrider,
+                            k -> new ArrayList<>());
+                    list.add(e.getKey());
+                }
+            });
+            inheritedMethods.addAll(pvmt.getAllVisibleMembers(Kind.METHODS));
+
+            // Copy the extra members (if any) from the lineage.
+            if (!utils.shouldDocument(pvmt.te)) {
+                List<? extends Element> extraMethods = pvmt.getExtraMembers(Kind.METHODS);
+
+                if (lmt.getOrderedMembers(Kind.METHODS).isEmpty()) {
+                    inheritedMethods.addAll(extraMethods);
+                    continue;
+                }
+
+                // Check if an extra-method ought to percolate through.
+                for (Element extraMethod : extraMethods) {
+                    boolean found = false;
+
+                    List<Element> lmethods = lmt.getMembers(extraMethod, Kind.METHODS);
+                    for (Element lmethod : lmethods) {
+                        ExecutableElement method = (ExecutableElement)lmethod;
+                        found = utils.elementUtils.overrides(method,
+                                (ExecutableElement)extraMethod, te);
+                        if (found)
+                            break;
+                    }
+                    if (!found)
+                        inheritedMethods.add(extraMethod);
+                }
+            }
+        }
+
+        // Filter out inherited methods that:
+        // a. cannot override (private instance members)
+        // b. are overridden and should not be visible in this type
+        // c. are hidden in the type being considered
+        // see allowInheritedMethods, which performs the above actions
+        List<Element> list = inheritedMethods.stream()
+                .filter(e -> allowInheritedMethods((ExecutableElement)e, overriddenByTable, lmt))
+                .collect(Collectors.toList());
+
+        // Filter out the local methods, that do not override or simply
+        // overrides a super method, or those methods that should not
+        // be visible.
+        Predicate<ExecutableElement> isVisible = m -> {
+            OverridingMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
+            return p == null || !p.simpleOverride;
+        };
+        List<Element> mlist = lmt.getOrderedMembers(Kind.METHODS);
+        List<Element> llist = mlist.stream()
+                .map(m -> (ExecutableElement)m)
+                .filter(isVisible)
+                .collect(Collectors.toList());
+
+        // Merge the above lists, making sure the local methods precede
+        // the others
+        list.addAll(0, llist);
+
+        // Final filtration of elements
+        list = list.stream()
+                .filter(this::mustDocument)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(Kind.METHODS, Collections.unmodifiableList(list));
+
+        // Copy over overridden tables from the lineage, and finish up.
+        for (VisibleMemberTable pvmt : parents) {
+            overriddenMethodTable.putAll(pvmt.overriddenMethodTable);
+        }
+        overriddenMethodTable = Collections.unmodifiableMap(overriddenMethodTable);
+    }
+
+    boolean isEnclosureInterface(Element e) {
+        TypeElement enclosing = utils.getEnclosingTypeElement(e);
+        return utils.isInterface(enclosing);
+    }
+
+    boolean allowInheritedMethods(ExecutableElement inheritedMethod,
+                                  Map<ExecutableElement, List<ExecutableElement>> inheritedOverriddenTable,
+                                  LocalMemberTable lmt) {
+
+        if (!isInherited(inheritedMethod))
+            return false;
+
+        final boolean haveStatic = utils.isStatic(inheritedMethod);
+        final boolean inInterface = isEnclosureInterface(inheritedMethod);
+
+        // Static methods in interfaces are never documented.
+        if (haveStatic && inInterface) {
+            return false;
+        }
+
+        // Multiple-Inheritance: remove the interface method that may have
+        // been overridden by another interface method in the hierarchy
+        //
+        // Note: The following approach is very simplistic and is compatible
+        // with old VMM. A future enhancement, may include a contention breaker,
+        // to correctly eliminate those methods that are merely definitions
+        // in favor of concrete overriding methods, for instance those that have
+        // API documentation and are not abstract OR default methods.
+        if (inInterface) {
+            List<ExecutableElement> list = inheritedOverriddenTable.get(inheritedMethod);
+            if (list != null) {
+                boolean found = list.stream()
+                        .anyMatch(this::isEnclosureInterface);
+                if (found)
+                    return false;
+            }
+        }
+
+        Elements elementUtils = config.docEnv.getElementUtils();
+
+        // Check the local methods in this type.
+        List<Element> lMethods = lmt.getMembers(inheritedMethod, Kind.METHODS);
+        for (Element lMethod : lMethods) {
+            // Ignore private methods or those methods marked with
+            // a "hidden" tag.
+            if (utils.isPrivate(lMethod))
+                continue;
+
+            // Remove methods that are "hidden", in JLS terms.
+            if (haveStatic && utils.isStatic(lMethod) &&
+                    elementUtils.hides(lMethod, inheritedMethod)) {
+                return false;
+            }
+
+            // Check for overriding methods.
+            if (elementUtils.overrides((ExecutableElement)lMethod, inheritedMethod,
+                    utils.getEnclosingTypeElement(lMethod))) {
+
+                // Disallow package-private super methods to leak in
+                TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
+                if (isUndocumentedEnclosure(encl)) {
+                    overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+                            l -> new OverridingMethodInfo(inheritedMethod, false));
+                    return false;
+                }
+                boolean simpleOverride = utils.isSimpleOverride((ExecutableElement)lMethod);
+                overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+                        l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
+                return simpleOverride;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * This class encapsulates the details of local members, orderedMembers
+     * contains the members in the declaration order, additionally a
+     * HashMap is maintained for performance optimization to lookup
+     * members. As a future enhancement is perhaps to consolidate the ordering
+     * into a Map, capturing the insertion order, thereby eliminating an
+     * ordered list.
+     */
+    class LocalMemberTable {
+
+        // Maintains declaration order
+        private final Map<Kind, List<Element>> orderedMembers;
+
+        // Performance optimization
+        private final Map<Kind, Map<String, List<Element>>> memberMap;
+
+        LocalMemberTable() {
+            orderedMembers = new EnumMap<>(Kind.class);
+            memberMap = new EnumMap<>(Kind.class);
+
+            List<? extends Element> elements = te.getEnclosedElements();
+            for (Element e : elements) {
+                if (config.nodeprecated && utils.isDeprecated(e)) {
+                    continue;
+                }
+                switch (e.getKind()) {
+                    case CLASS:
+                    case INTERFACE:
+                    case ENUM:
+                    case ANNOTATION_TYPE:
+                        addMember(e, Kind.INNER_CLASSES);
+                        break;
+                    case FIELD:
+                        addMember(e, Kind.FIELDS);
+                        addMember(e, Kind.ANNOTATION_TYPE_FIELDS);
+                        break;
+                    case METHOD:
+                        ExecutableElement ee = (ExecutableElement)e;
+                        if (utils.isAnnotationType(te)) {
+                            addMember(e, ee.getDefaultValue() == null
+                                    ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
+                                    : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+                        }
+                        addMember(e, Kind.METHODS);
+                        break;
+                    case CONSTRUCTOR:
+                        if (!utils.isEnum(te))
+                            addMember(e, Kind.CONSTRUCTORS);
+                        break;
+                    case ENUM_CONSTANT:
+                        addMember(e, Kind.ENUM_CONSTANTS);
+                        break;
+                }
+            }
+
+            // Freeze the data structures
+            for (Kind kind : Kind.values()) {
+                orderedMembers.computeIfPresent(kind, (k, v) -> Collections.unmodifiableList(v));
+                orderedMembers.computeIfAbsent(kind, t -> Collections.emptyList());
+
+                memberMap.computeIfPresent(kind, (k, v) -> Collections.unmodifiableMap(v));
+                memberMap.computeIfAbsent(kind, t -> Collections.emptyMap());
+            }
+        }
+
+        String getMemberKey(Element e) {
+            return new SimpleElementVisitor9<String, Void>() {
+                @Override
+                public String visitExecutable(ExecutableElement e, Void aVoid) {
+                    return e.getSimpleName() + ":" + e.getParameters().size();
+                }
+
+                @Override
+                protected String defaultAction(Element e, Void aVoid) {
+                    return e.getSimpleName().toString();
+                }
+            }.visit(e);
+        }
+
+        void addMember(Element e, Kind kind) {
+            List<Element> list = orderedMembers.computeIfAbsent(kind, k -> new ArrayList<>());
+            list.add(e);
+
+            Map<String, List<Element>> map = memberMap.computeIfAbsent(kind, k -> new HashMap<>());
+            list = map.computeIfAbsent(getMemberKey(e), l -> new ArrayList<>());
+            list.add(e);
+        }
+
+        List<Element> getOrderedMembers(Kind kind) {
+            return orderedMembers.get(kind);
+        }
+
+        List<Element> getMembers(Element e, Kind kind) {
+            String key = getMemberKey(e);
+            return getMembers(key, kind);
+        }
+
+        List<Element> getMembers(String key, Kind kind) {
+            Map <String, List<Element>> map = memberMap.get(kind);
+            return map.getOrDefault(key, Collections.emptyList());
+        }
+
+        List<Element> getPropertyMethods(String methodName, int argcount) {
+            return getMembers(methodName + ":" + argcount, Kind.METHODS).stream()
+                    .filter(m -> (utils.isPublic(m) || utils.isProtected(m)))
+                    .collect(Collectors.toList());
+        }
+    }
+
+    /**
+     * The properties triad for a property method.
+     */
+    static class PropertyMembers {
+        final VariableElement field;
+        final ExecutableElement getter;
+        final ExecutableElement setter;
+
+        PropertyMembers(VariableElement field, ExecutableElement getter, ExecutableElement setter) {
+            this.field = field;
+            this.getter = getter;
+            this.setter = setter;
+        }
+
+        public String toString() {
+            return ("field: " + field + ", getter: " + getter + ", setter: " + setter);
+        }
+    }
+
+    /*
+     * JavaFX convention notes.
+     * A JavaFX property-method is a method, which ends with "Property" in
+     * its name, takes no parameters and typically returns a subtype of javafx.beans.
+     * ReadOnlyProperty, in the strictest sense. However, it may not always
+     * be possible for the doclet to have access to j.b.ReadOnlyProperty,
+     * for this reason the strict check is disabled via an undocumented flag.
+     *
+     * Note, a method should not be considered as a property-method,
+     * if it satisfied the previously stated conditions AND if the
+     * method begins with "set", "get" or "is".
+     *
+     * Supposing we have  {@code BooleanProperty acmeProperty()}, then the
+     * property-name  is "acme".
+     *
+     * Property field, one may or may not exist and could be private, and
+     * should match the property-method.
+     *
+     * A property-setter is a method starting with "set", and the
+     * first character of the upper-cased starting character of the property name, the
+     * method must take 1 argument and must return a <code>void</code>.
+     *
+     * Using the above example {@code void setAcme(Something s)} can be
+     * considered as a property-setter of the property "acme".
+     *
+     * A property-getter is a method  starting with "get" and the first character
+     * upper-cased property-name, having no parameters. A method that does not take any
+     * parameters and starting with "is" and an upper-cased property-name,
+     * returning a primitive type boolean or BooleanProperty can also be
+     * considered as a getter, however there must be only one getter for every property.
+     *
+     * For example {@code Object getAcme()} is a property-getter, and
+     * {@code boolean isFoo()}
+     */
+    private void computeVisibleProperties(LocalMemberTable lmt) {
+        if (!config.javafx)
+            return;
+
+        PropertyUtils pUtils = config.propertyUtils;
+        List<ExecutableElement> list = visibleMembers.getOrDefault(Kind.METHODS, Collections.emptyList())
+                .stream()
+                .map(m -> (ExecutableElement)m)
+                .filter(pUtils::isPropertyMethod)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(Kind.PROPERTIES, Collections.unmodifiableList(list));
+
+        List<ExecutableElement> propertyMethods = list.stream()
+                .filter(e -> utils.getEnclosingTypeElement(e) == te)
+                .collect(Collectors.toList());
+
+        // Compute additional properties related sundries.
+        for (ExecutableElement propertyMethod : propertyMethods) {
+            String baseName = pUtils.getBaseName(propertyMethod);
+            List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
+            Element field = flist.isEmpty() ? null : flist.get(0);
+
+            Element getter = null, setter = null;
+            List<Element> found = lmt.getPropertyMethods(pUtils.getGetName(propertyMethod), 0);
+            if (!found.isEmpty()) {
+                // Getters have zero params, no overloads! pick the first.
+                getter = found.get(0);
+            }
+            if (getter == null) {
+                // Check if isProperty methods are present ?
+                found = lmt.getPropertyMethods(pUtils.getIsName(propertyMethod), 0);
+                if (!found.isEmpty()) {
+                    String propertyTypeName = propertyMethod.getReturnType().toString();
+                    // Check if the return type of property method matches an isProperty method.
+                    if (pUtils.hasIsMethod(propertyMethod)) {
+                        // Getters have zero params, no overloads!, pick the first.
+                        getter = found.get(0);
+                    }
+                }
+            }
+            found = lmt.getPropertyMethods(pUtils.getSetName(propertyMethod), 1);
+            if (found != null) {
+                for (Element e : found) {
+                    if (pUtils.isValidSetterMethod((ExecutableElement)e)) {
+                        setter = e;
+                        break;
+                    }
+                }
+            }
+
+            propertyMap.put(propertyMethod, new PropertyMembers((VariableElement)field,
+                    (ExecutableElement)getter, (ExecutableElement)setter));
+
+            // Debugging purposes
+            // System.out.println("te: " + te + ": " + utils.getEnclosingTypeElement(propertyMethod) +
+            //        ":" + propertyMethod.toString() + "->" + propertyMap.get(propertyMethod));
+        }
+    }
+
+
+    // Future cleanups
+
+    Map<ExecutableElement, SoftReference<ImplementedMethods>> implementMethodsFinders = new HashMap<>();
+
+    private ImplementedMethods getImplementedMethodsFinder(ExecutableElement method) {
+        SoftReference<ImplementedMethods> imf = implementMethodsFinders.get(method);
+        // IMF does not exist or referent was gc'ed away ?
+        if (imf == null || imf.get() == null) {
+            imf = new SoftReference<>(new ImplementedMethods(method));
+            implementMethodsFinders.put(method, imf);
+        }
+        return imf.get();
+    }
+
+    public List<ExecutableElement> getImplementedMethods(ExecutableElement method) {
+        ImplementedMethods imf = getImplementedMethodsFinder(method);
+        return imf.getImplementedMethods().stream()
+                .filter(m -> getsimplyOverriddenMethod(m) == null)
+                .collect(Collectors.toList());
+    }
+
+    public TypeMirror getImplementedMethodHolder(ExecutableElement method,
+                                                 ExecutableElement implementedMethod) {
+        ImplementedMethods imf = getImplementedMethodsFinder(method);
+        return imf.getMethodHolder(implementedMethod);
+    }
+
+    private class ImplementedMethods {
+
+        private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
+        private final List<ExecutableElement> methlist = new ArrayList<>();
+        private final TypeElement typeElement;
+        private final ExecutableElement method;
+
+        public ImplementedMethods(ExecutableElement method) {
+            this.method = method;
+            typeElement = utils.getEnclosingTypeElement(method);
+            Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
+            /*
+             * Search for the method in the list of interfaces. If found check if it is
+             * overridden by any other subinterface method which this class
+             * implements. If it is not overidden, add it in the method list.
+             * Do this recursively for all the extended interfaces for each interface
+             * from the list.
+             */
+            for (TypeMirror interfaceType : intfacs) {
+                ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
+                if (found != null) {
+                    removeOverriddenMethod(found);
+                    if (!overridingMethodFound(found)) {
+                        methlist.add(found);
+                        interfaces.put(found, interfaceType);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Return the list of interface methods which the method passed in the
+         * constructor is implementing. The search/build order is as follows:
+         * <pre>
+         * 1. Search in all the immediate interfaces which this method's class is
+         *    implementing. Do it recursively for the superinterfaces as well.
+         * 2. Traverse all the superclasses and search recursively in the
+         *    interfaces which those superclasses implement.
+         *</pre>
+         *
+         * @return SortedSet<ExecutableElement> of implemented methods.
+         */
+        List<ExecutableElement> getImplementedMethods() {
+            return methlist;
+        }
+
+        TypeMirror getMethodHolder(ExecutableElement ee) {
+            return interfaces.get(ee);
+        }
+
+        /**
+         * Search in the method list and check if it contains a method which
+         * is overridden by the method as parameter.  If found, remove the
+         * overridden method from the method list.
+         *
+         * @param method Is this method overriding a method in the method list.
+         */
+        private void removeOverriddenMethod(ExecutableElement method) {
+            TypeElement overriddenClass = utils.overriddenClass(method);
+            if (overriddenClass != null) {
+                for (int i = 0; i < methlist.size(); i++) {
+                    TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
+                    if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
+                        methlist.remove(i);  // remove overridden method
+                        return;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Search in the already found methods' list and check if it contains
+         * a method which is overriding the method parameter or is the method
+         * parameter itself.
+         *
+         * @param method method to be searched
+         */
+        private boolean overridingMethodFound(ExecutableElement method) {
+            TypeElement containingClass = utils.getEnclosingTypeElement(method);
+            for (ExecutableElement listmethod : methlist) {
+                if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
+                    // it's the same method.
+                    return true;
+                }
+                TypeElement te = utils.overriddenClass(listmethod);
+                if (te == null) {
+                    continue;
+                }
+                if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * A simple container to encapsulate an overriding method
+     * and the type of override.
+     */
+    static class OverridingMethodInfo {
+        final ExecutableElement overrider;
+        final boolean simpleOverride;
+
+        public OverridingMethodInfo(ExecutableElement overrider, boolean simpleOverride) {
+            this.overrider = overrider;
+            this.simpleOverride = simpleOverride;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, 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 8025091
+ * @summary Tests the basic selection of FX related property methods, fields,
+ *          setters and getters, by executing this test in the strict mode.
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester propgen.PropGen
+ * @run main TestFxProperties
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class TestFxProperties extends JavadocTester {
+
+    public static void main(String... args) throws Exception {
+        TestFxProperties tester = new TestFxProperties();
+        if (!tester.sanity()) {
+            return;
+        }
+        tester.runTests();
+    }
+
+    // Check if FX modules are available.
+    boolean sanity() {
+        ClassLoader cl = this.getClass().getClassLoader();
+        try {
+            cl.loadClass("javafx.beans.Observable");
+        } catch (ClassNotFoundException cnfe) {
+            System.out.println("Note: javafx.beans.Observable: not found, test passes vacuously");
+            return false;
+        }
+        return true;
+    }
+
+    @Test
+    void test1() throws Exception {
+        Path srcdir = Paths.get("src-propgen");
+        Files.createDirectory(srcdir);
+        new propgen.PropGen(srcdir).run();
+        Path srcfile = Paths.get(srcdir.toString(), "Demo.java");
+
+        javadoc("-d", "out-propgen",
+                "--javafx",
+                srcfile.toString());
+        checkExit(Exit.OK);
+        checkOrder("Demo.html",
+                "PROPERTY SUMMARY",
+                "Property for fgp.",
+                "Property for fgsp.",
+                "Property for fp.",
+                "Property for fsp.",
+                "Property for gp.",
+                "Property for gsp.",
+                "Property for p.",
+                "Property for sp.",
+                "FIELD SUMMARY",
+                "Field for f.",
+                "Field for fg.",
+                "Field for fgp.",
+                "Field for fgs.",
+                "Field for fgsp.",
+                "Field for fp.",
+                "Field for fs.",
+                "Field for fsp.",
+                "CONSTRUCTOR SUMMARY"
+        );
+
+        checkOrder("Demo.html",
+                "METHOD SUMMARY",
+                "Getter for fg.",
+                "Getter for fgp.",
+                "Getter for fgs.",
+                "Getter for fgsp.",
+                "Getter for g.",
+                "Getter for gp.",
+                "Getter for gs.",
+                "Getter for gsp.",
+                "Setter for fgs.",
+                "Setter for fgsp.",
+                "Setter for fs.",
+                "Setter for fsp.",
+                "Setter for gs.",
+                "Setter for gsp.",
+                "Setter for s.",
+                "Setter for sp.",
+                "Methods inherited");
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Tue Apr 24 11:54:03 2018 -0700
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
- *      8167967 8172528 8175200 8178830 8182257 8186332 8182765
+ *      8167967 8172528 8175200 8178830 8182257 8186332 8182765 8025091
  * @summary Test of the JavaFX doclet features.
  * @author jvalenta
  * @library ../lib
@@ -45,6 +45,7 @@
         javadoc("-d", "out1",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg1");
         checkExit(Exit.OK);
@@ -174,6 +175,7 @@
                 "-html4",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg1");
         checkExit(Exit.OK);
@@ -200,6 +202,7 @@
         javadoc("-d", "out2a",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg2");
         checkExit(Exit.OK);
@@ -255,6 +258,7 @@
                 "-html4",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg2");
         checkExit(Exit.OK);
@@ -390,6 +394,7 @@
     void test4() {
         javadoc("-d", "out4",
                 "--javafx",
+                "--disable-javafx-strict-checks",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-package",
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java	Tue Apr 24 11:54:03 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -60,27 +60,28 @@
 
     public final void setRate(double value) {}
 
-    public final double getRate() {}
+    public final double getRate() { return 1.0d; }
 
-    public final DoubleProperty rateProperty() {}
+    public final DoubleProperty rateProperty() { return null; }
 
     private BooleanProperty paused;
 
     public final void setPaused(boolean value) {}
 
-    public final double isPaused() {}
+    public final double isPaused() { return 3.14d; }
 
     /**
      * Defines if paused. The second line.
      * @defaultValue false
+     * @return foo
      */
-    public final BooleanProperty pausedProperty() {}
+    public final BooleanProperty pausedProperty() { return null; }
 
     class DoubleProperty {}
 
     class BooleanProperty {}
 
-    public final BooleanProperty setTestMethodProperty() {}
+    public final BooleanProperty setTestMethodProperty() { return null; }
 
     private class Inner {
         private BooleanProperty testMethodProperty() {}
@@ -94,8 +95,8 @@
 
         public final void setRate(double value) {}
 
-        public final double getRate() {}
+        public final double getRate() { return 3.14d; }
 
-        public final DoubleProperty rateProperty() {}
+        public final DoubleProperty rateProperty() { return null; }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/propgen/PropGen.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+package propgen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PropGen {
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) throws IOException {
+        new PropGen().run();
+    }
+
+    final PrintStream out;
+
+    final Path outFile;
+    final ByteArrayOutputStream baos;
+
+    PropGen() {
+        out = System.out;
+        outFile = null;
+        baos = null;
+    }
+
+    public PropGen(Path outDir) throws IOException {
+        outFile = Paths.get(outDir.toString(), "Demo.java");
+        baos = new ByteArrayOutputStream();
+        out = new PrintStream(baos);
+    }
+
+    enum Kind {
+        FIELD(1),
+        GETTER(2),
+        SETTER(4),
+        PROPERTY(8);
+        Kind(int bit) {
+            this.bit = bit;
+        }
+        int bit;
+    }
+
+    public void run() throws IOException {
+        out.println("import javafx.beans.property.Property;");
+        out.println("public class Demo {");
+        for (int i = 1; i < 16; i++) {
+            Set<Kind> set = EnumSet.noneOf(Kind.class);
+            for (Kind k : Kind.values()) {
+                if ((i & k.bit) == k.bit) {
+                    set.add(k);
+                }
+            }
+            addItems(set);
+        }
+        out.println("}");
+        if (baos != null && outFile != null) {
+            Files.write(outFile, baos.toByteArray());
+        }
+    }
+
+    void addItems(Set<Kind> kinds) {
+        String name = kinds.stream()
+                .map(k -> k.name())
+                .map(s -> s.substring(0, 1))
+                .collect(Collectors.joining(""))
+                .toLowerCase();
+        if (kinds.contains(Kind.FIELD)) {
+            out.println("    /** Field for " + name + ". */");
+            out.println("    public Property " + name + ";");
+        }
+        if (kinds.contains(Kind.GETTER)) {
+            out.println("    /**");
+            out.println("     * Getter for " + name + ".");
+            out.println("     * @return a " + name);
+            out.println("     */");
+            out.println("    public Object " + mname("get", name) + "() { return null; }");
+        }
+        if (kinds.contains(Kind.SETTER)) {
+            out.println("    /**");
+            out.println("     * Setter for " + name + ".");
+            out.println("     * @param o a " + name);
+            out.println("     */");
+            out.println("    public void " + mname("set", name) + "(Object o) {  }");
+        }
+        if (kinds.contains(Kind.PROPERTY)) {
+            out.println("    /**");
+            out.println("     * Property for " + name + ".");
+            out.println("     * @return the property for " + name);
+            out.println("     */");
+            out.println("    public Property " + name + "Property() { return null; }");
+        }
+        out.println();
+    }
+
+    String mname(String prefix, String base) {
+        return prefix + Character.toUpperCase(base.charAt(0)) + base.substring(1);
+    }
+
+}
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Tue Apr 24 11:54:03 2018 -0700
@@ -181,6 +181,7 @@
         javadoc("-d", "out-9",
                 "-linksource",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "-package",
                 "linksource");
@@ -254,6 +255,7 @@
                 "-html4",
                 "-linksource",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "-package",
                 "linksource");
--- a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Tue Apr 24 11:54:03 2018 -0700
@@ -578,6 +578,7 @@
         void run() {
             tester.javadoc("-d", "out-5",
                     "-javafx",
+                    "--disable-javafx-strict-checks",
                     "-sourcepath", tester.testSrc(new File(".").getPath()),
                     "pkg5"
             );
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Tue Apr 24 11:54:03 2018 -0700
@@ -43,6 +43,7 @@
         javadoc("-d", "out-bad-option",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=nonsense",
                 "pkg5");
 
@@ -55,6 +56,7 @@
         javadoc("-d", "out-detail",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=detail",
                 "pkg5");
 
@@ -66,6 +68,7 @@
         javadoc("-d", "out-summary",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=summary",
                 "pkg5");
 
--- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java	Tue Apr 24 11:54:03 2018 -0700
@@ -42,6 +42,7 @@
     void testArrays() {
         javadoc("-d", "out",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "pkg");
         checkExit(Exit.OK);
@@ -113,6 +114,7 @@
         javadoc("-d", "out-html4",
                 "-html4",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "pkg");
         checkExit(Exit.OK);
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Tue Apr 24 16:48:29 2018 -0700
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Tue Apr 24 11:54:03 2018 -0700
@@ -285,6 +285,7 @@
         javadoc("-d", "out-9",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "-use",
                 "pkgfx", "pkg3");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2002, 2018, 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 8025091 8198890
+ * @summary Verify the presence visible members in the case of
+ *          member hiding and overridding.
+ * @library /tools/lib ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester toolbox.ToolBox builder.ClassBuilder
+ * @run main TestVisibleMembers
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import builder.AbstractBuilder;
+import builder.AbstractBuilder.Comment.Kind;
+import builder.ClassBuilder;
+import builder.ClassBuilder.*;
+
+import toolbox.ToolBox;
+import builder.ClassBuilder;
+
+public class TestVisibleMembers extends JavadocTester {
+
+    final ToolBox tb;
+    public static void main(String... args) throws Exception {
+        TestVisibleMembers tester = new TestVisibleMembers();
+        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    TestVisibleMembers() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    void testChronoDiamondLeafDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitChronoDiamondLeaf(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+                "C", "with", "java.lang.Object", "obj",  "Method with in p.C",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+                "METHOD DETAIL");
+        checkOutput("p/C.html", false, "BImpl");
+
+        checkOrder("p/E.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+                "C", "with", "java.lang.Object", "Method with in p.E",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.E",
+                "METHOD DETAIL");
+        checkOutput("p/E.html", false, "EImpl");
+    }
+
+    @Test
+    void testChronoDiamondLeafSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitChronoDiamondLeaf(srcDir);
+
+        Path outDir = base.resolve("out-member");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+                "C", "with", "java.lang.Object", "obj", "Method with in p.C",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+                "METHOD DETAIL");
+        checkOutput("p/C.html", false, "BImpl");
+
+        checkOrder("p/E.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+                "C", "with", "java.lang.Object", "Method with in p.E",
+                "C", "with", "java.lang.Object", "long", "lvalue", "Method with in p.E",
+                "METHOD DETAIL");
+        checkOutput("p/E.html", false, "EImpl");
+    }
+
+    // see j.t.TemporalAdjuster
+    void emitChronoDiamondLeaf(Path srcDir) throws Exception {
+
+        // Interface A
+        MethodBuilder mbWith1 = MethodBuilder
+                .parse("default Object with(Object obj) {return null;}");
+        MethodBuilder mbWith2 = MethodBuilder
+                .parse("default Object with(Object obj, long lvalue) {return null;}");
+
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("public", "interface")
+                .addMembers(mbWith1, mbWith2)
+                .write(srcDir);
+
+        // Interface B
+        mbWith1.setComments("{@inheritDoc}", "@param obj an object",
+                "@return something");
+
+        mbWith2.setComments("{@inheritDoc}", "@param obj an object",
+                "@param lvalue an lvalue", "@return something");
+
+        new ClassBuilder(tb, "p.B")
+                .setModifiers( "public", "interface")
+                .setExtends("A")
+                .addMembers(mbWith1, mbWith2)
+                .write(srcDir);
+
+        // Class BImpl
+        MethodBuilder mb31 = MethodBuilder.parse("C with(Object obj) {return null;}");
+        MethodBuilder mb32 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+        new ClassBuilder(tb, "p.BImpl<C extends B>")
+                .setModifiers( "abstract", "class")
+                .addImplements("B")
+                .addMembers(mb31, mb32)
+                .write(srcDir);
+
+        // Class C
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("BImpl")
+                .addMembers(mbWith1.setReturn("C")
+                        .setModifiers("public")
+                        .setComments(AbstractBuilder.Comment.Kind.AUTO))
+                .addMembers(mbWith2.setReturn("C")
+                        .setModifiers("public")
+                        .setComments(AbstractBuilder.Comment.Kind.AUTO))
+                .addMembers(MethodBuilder.parse("public boolean equals(Object obj) { return false;}"))
+                .write(srcDir);
+
+        // Class EImpl
+        MethodBuilder mb41 = MethodBuilder.parse("C with(Object obj) {return null;}")
+                .setComments(Kind.NO_API_COMMENT);
+        MethodBuilder mb42 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+        new ClassBuilder(tb, "p.EImpl<C extends B>")
+                .setModifiers( "abstract", "class")
+                .addImplements("B")
+                .addMembers(mb41, mb42)
+                .write(srcDir);
+
+        // Class E
+        MethodBuilder mb51 = MethodBuilder.parse("public C with(Object obj) {return null;}");
+        MethodBuilder mb52 = MethodBuilder.parse("public C with(Object obj, long lvalue) {return null;}");
+        MethodBuilder mb53 = MethodBuilder.parse("public boolean equals(Object obj) { return false;}");
+        new ClassBuilder(tb, "p.E")
+                .setModifiers("public", "class")
+                .setExtends("EImpl")
+                .addMembers(mb51, mb52, mb53)
+                .write(srcDir);
+    }
+
+    @Test
+    void testNestedInterfaceDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitNestedInterface(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/TA.html", false, "getTA");
+
+        checkOrder("p/Bar.html",
+                "doSomething()",
+                "getTA()");
+    }
+
+    @Test
+    void testNestedInterfaceSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitNestedInterface(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/TA.html", false, "getTA");
+
+        checkOrder("p/Bar.html",
+                "doSomething()",
+                "getTA()");
+
+        checkOrder("p/Foo.html",
+                "Methods declared in",
+                "Bar.html",
+                "getTA");
+    }
+
+    // See jx.s.TransferHandler
+    void emitNestedInterface(Path srcDir) throws Exception {
+
+        ClassBuilder innerI = new ClassBuilder(tb, "HasTA")
+                .setModifiers("interface");
+        MethodBuilder interfaceMethod = MethodBuilder.parse("public TA getTa();")
+                .setComments(Kind.NO_API_COMMENT);
+        innerI.addMembers(interfaceMethod);
+
+        new ClassBuilder(tb, "p.TA")
+                .setModifiers("public", "class")
+                .addImplements("java.io.Serializable")
+                .addNestedClasses(innerI)
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.Foo")
+                .setModifiers("public", "class")
+                .setExtends("Bar")
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.Bar")
+                .setModifiers("public", "abstract", "class")
+                .addImplements("TA.HasTA")
+                .addMembers(
+                    MethodBuilder.parse("public void doSomething(){}"),
+                    MethodBuilder.parse("public TA getTA(){return null;}")
+                ).write(srcDir);
+    }
+
+    @Test
+    void testStreamsMissingLinksDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitStreamsMissingLinks(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "method()",
+                "See Also:",
+                "sub()",
+                "sub1()");
+
+        checkOrder("p/ILong.html",
+                "METHOD DETAIL",
+                "default", "void", "forEach", "java.util.function.Consumer",
+                "java.lang.Long", "action",
+                "Do you see me", "#forEach(java.util.function.LongConsumer)",
+                "forEach(LongConsumer)",
+                "END OF CLASS DATA");
+
+        checkOrder("p/IImpl.html",
+                "METHOD DETAIL",
+                "Method sub in p.IImpl",
+                "Specified by:", "I.html", "II.html",
+                "END OF CLASS DATA");
+    }
+
+    @Test
+    void testStreamsMissingLinksSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitStreamsMissingLinks(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "method()", "See Also:", "sub()", "I.sub1()",
+                "public", "void", "m", "Method in C. See", "I.length()"
+                );
+
+        checkOrder("p/ILong.html",
+                "METHOD DETAIL",
+                "default", "void", "forEach", "java.util.function.Consumer",
+                "java.lang.Long", "action",
+                "Do you see me", "QLong.html#forEach(Q)",
+                "QLong.forEach(LongConsumer)",
+                "END OF CLASS DATA");
+
+        checkOrder("p/IImpl.html",
+                "METHOD DETAIL",
+                "Method sub in p.IImpl",
+                "Specified by:", "I.html",
+                "END OF CLASS DATA");
+
+        checkUnique("p/IImpl.html", "Specified by:");
+    }
+
+    // see j.u.Spliterator
+    void emitStreamsMissingLinks(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.I")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        MethodBuilder.parse("public I sub();"),
+                        MethodBuilder.parse("public I sub1();"),
+                        MethodBuilder.parse("public int length();")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("abstract", "class")
+                .addImplements("I")
+                .addMembers(
+                        MethodBuilder.parse("public I sub() {}"),
+                        MethodBuilder.parse("public I sub1() {}"),
+                        MethodBuilder.parse("public int length(){return 0;}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void m(){}")
+                        .setComments("Method in C. See {@link #length()}.")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("A").addImplements("I")
+                .addMembers(
+                        MethodBuilder.parse("public I sub() {return null;}"),
+                        MethodBuilder.parse("public I sub1() {return null;}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse(" public void method() {}")
+                                .setComments("A method ", "@see #sub", "@see #sub1"),
+                        MethodBuilder.parse("public int length(){return 1;}")
+                                .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.II")
+                .setModifiers("public", "interface")
+                .setExtends("I")
+                .addMembers(
+                        MethodBuilder.parse("default public I sub() {return null;}")
+                            .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.IImpl")
+                .setModifiers("public", "class")
+                .addImplements("II")
+                .addMembers(
+                    MethodBuilder.parse("public I sub() {return null;}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.QLong<P, Q, R>")
+                .setModifiers("public interface")
+                .addMembers(
+                        MethodBuilder.parse("default void forEach(Q action) {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.ILong")
+                .addImports("java.util.function.*")
+                .setModifiers("public", "interface")
+                .setExtends("QLong<Long, LongConsumer, Object>")
+                .addMembers(
+                        MethodBuilder.parse("default void forEach(LongConsumer action) {}")
+                            .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("default void forEach(Consumer<Long> action) {}")
+                            .setComments("Do you see me {@link #forEach(LongConsumer)} ?")
+                ).write(srcDir);
+    }
+
+    @Test
+    void testVisibleMemberTableDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitVisibleMemberTable(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "m()", "Method m in p.B",
+                "public", "void", "n()", "Method n in p.A",
+                "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+                "public", "void", "p()", "Method p in p.B",
+                "END OF CLASS DATA");
+
+        checkOutput("p/C.html", false,
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/D.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.D",
+                "void", "n", "Method n in p.D",
+                "void", "o", "Method o in p.D",
+                "void", "p", "Method p in p.D",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/D.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/E.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/E.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+    }
+
+    @Test
+    void testVisibleMemberTableSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitVisibleMemberTable(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "m()", "Method m in p.B",
+                "public", "void", "n()", "Method n in p.A",
+                "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+                "public", "void", "p()", "Method p in p.B",
+                "END OF CLASS DATA");
+
+        checkOutput("p/C.html", false,
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/D.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.D",
+                "void", "n", "Method n in p.D",
+                "void", "o", "Method o in p.D",
+                "void", "p", "Method p in p.D",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/D.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/E.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/E.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+    }
+
+    // emit a matrix of method variants
+    void emitVisibleMemberTable(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("public", "class")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}"),
+                        MethodBuilder.parse("public void o() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.B")
+                .setModifiers("class")
+                .setExtends("A")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void o() {}")
+                        .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void p() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void o() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void p() {}")
+                                .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.D")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}"),
+                        MethodBuilder.parse("public void o() {}"),
+                        MethodBuilder.parse("public void p() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.E")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void o() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void p() {}")
+                                .setComments(Kind.INHERIT_DOC)
+                ).write(srcDir);
+    }
+
+    @Test
+    void testHiddenMembersDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitHiddenMembers(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C1.html",
+                "FIELD SUMMARY",
+                "Fields inherited from interface", "I1", "field2",
+                "Fields inherited from interface", "I2", "field2",
+                "Fields inherited from interface", "I3", "field",
+                "METHOD SUMMARY",
+                "Methods inherited from interface", "I1", "method2",
+                "Methods inherited from interface", "I2", "method2",
+                "Methods inherited from interface", "I3", "method",
+                "CONSTRUCTOR DETAIL");
+
+        checkOrder("p/C2.html",
+                "FIELD SUMMARY",
+                "int", "field", "Field field in p.C2",
+                "Fields inherited from interface", "I1", "field2",
+                "Fields inherited from interface", "I2", "field2",
+                "METHOD SUMMARY",
+                "void", "method", "Method method in p.C2",
+                "void", "method2", "Method method2 in p.C2");
+
+    }
+
+    @Test
+    void testHiddenMembersSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitHiddenMembers(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C1.html",
+                "Field Summary",
+                "Fields declared in interface", "I1", "field2",
+                "Fields declared in interface", "I2", "field2",
+                "Fields declared in interface", "I3", "field",
+                "Method Summary",
+                "Methods declared in interface", "I1", "method2",
+                "Methods declared in interface", "I2", "method2",
+                "Methods declared in interface", "I3", "method",
+                "Constructor Detail");
+
+        checkOrder("p/C2.html",
+                "Field Summary",
+                "int", "field", "Field field in p.C2",
+                "Fields declared in interface", "I1", "field2",
+                "Fields declared in interface", "I2", "field2",
+                "Method Summary",
+                "void", "method", "Method method in p.C2",
+                "void", "method2", "Method method2 in p.C2");
+
+    }
+
+    void emitHiddenMembers(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.I1")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        FieldBuilder.parse("public static int field2 = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public void method2();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.I2")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        FieldBuilder.parse("public static int field2 = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public void method2();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.I3")
+                .setExtends("I1, I2")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C1")
+                .setModifiers("public", "abstract", "class")
+                .addImplements("I3")
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.C2")
+                .setExtends("C1")
+                .setModifiers("public", "abstract", "class")
+                .addMembers(
+                        FieldBuilder.parse("public int field;"),
+                        MethodBuilder.parse("public void method(){}"),
+                        MethodBuilder.parse("public void method2(){}")
+                ).write(srcDir);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/AbstractBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2018, 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 builder;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class AbstractBuilder {
+
+    final String name;
+
+    Modifiers modifiers;
+    Comment comments;
+    String cname;
+
+    /**
+     * Constructs the base builder.
+     * @param modifiers for the class
+     * @param name of the element
+     */
+    public AbstractBuilder(Modifiers modifiers, String name) {
+        this.modifiers = modifiers;
+        this.name = name;
+        this.comments = new Comment(Comment.Kind.AUTO);
+    }
+
+    AbstractBuilder setModifiers(String... mods) {
+        this.modifiers = new Modifiers(mods);
+        return this;
+    }
+
+    /**
+     * Sets the enclosing type's name.
+     * @param className the enclosing type's name
+     */
+    void setClassName(String className) {
+        this.cname = className;
+    }
+
+    /**
+     * Sets the comment type for the member.
+     * @param comment for the member.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(Comment comment) {
+        this.comments = comment;
+        return this;
+    }
+
+    /**
+     * Sets the comments for the member.
+     * @param comments for the member.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(String... comments) {
+        this.comments = new Comment(comments);
+        return this;
+    }
+
+    /**
+     * Sets a comment for the element. Typically used to set
+     * user's preferences whether an automatic comment is
+     * required or no API comment.
+     *
+     * @param kind of comment, automatic or no comment.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(Comment.Kind kind) {
+        switch (kind) {
+            case NO_API_COMMENT: case AUTO: case INHERIT_DOC:
+                this.comments = new Comment(kind);
+                break;
+            default:
+                throw new IllegalArgumentException(kind + " not allowed");
+        }
+        return this;
+    }
+
+    /**
+     * The comment container.
+     */
+    public static class Comment {
+
+        /**
+         * The kinds of a comment.
+         */
+        public enum Kind {
+            /**
+             * user specified
+             */
+            USER,
+            /**
+             * no API comments
+             */
+            NO_API_COMMENT,
+            /**
+             * inserts the javadoc tag
+             */
+            INHERIT_DOC,
+            /**
+             * auto generate one
+             */
+            AUTO
+        }
+
+        final Kind kind;
+        final List<String> comments;
+
+        /**
+         * Construct an initial comment.
+         *
+         * @param kind
+         */
+        public Comment(Kind kind) {
+            this.kind = kind;
+            comments = Collections.emptyList();
+        }
+
+        /**
+         * Specify a user comment.
+         *
+         * @param comments the string of API comments.
+         */
+        public Comment(String... comments) {
+            kind = Kind.USER;
+            this.comments = comments == null
+                    ? Collections.emptyList()
+                    : List.of(comments);
+        }
+
+        @Override
+        public String toString() {
+            ClassBuilder.OutputWriter ow = new ClassBuilder.OutputWriter();
+            switch (kind) {
+                case USER:
+                    comments.forEach((s) -> ow.println("  " + s));
+                    break;
+                case INHERIT_DOC:
+                    ow.println("{@inheritDoc}");
+                    break;
+            }
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The modifier representation for an element.
+     */
+    public static class Modifiers {
+        List<String> modifiers;
+
+        /**
+         * Constructs a modifier container.
+         * @param modifiers for an element.
+         */
+        public Modifiers(String... modifiers) {
+            this.modifiers = List.of(modifiers);
+        }
+
+        /**
+         * Constructs a modifier container.
+         * @param modifiers a list of modifier strings.
+         */
+        public Modifiers(List<String> modifiers) {
+            this.modifiers = modifiers;
+        }
+
+        /**
+         * Sets the modifiers for this element.
+         * @param modifiers
+         */
+        public void setModifiers(String... modifiers) {
+            this.modifiers = List.of(modifiers);
+        }
+
+        /**
+         * Sets the modifiers for this element.
+         * @param modifiers
+         */
+        public void setModifiers(List<String> modifiers) {
+            this.modifiers = modifiers;
+        }
+
+        @Override
+        public String toString() {
+            OutputWriter ow = new OutputWriter();
+            modifiers.forEach(i -> ow.print(i + " "));
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The output writer.
+     */
+    public static class OutputWriter {
+        private final StringWriter sw = new StringWriter();
+        private final PrintWriter pw = new PrintWriter(sw);
+
+        @Override
+        public String toString() {
+            return sw.getBuffer().toString();
+        }
+
+        /**
+         * Prints a string without NL.
+         * @param s the string to print.
+         */
+        public void print(String s) {
+            pw.print(s);
+        }
+
+        /**
+         * Prints a string with a NL.
+         * @param s the string to print.
+         */
+        public void println(String s) {
+            pw.println(s);
+        }
+    }
+
+    /**
+     * A container to encapsulate a pair of values.
+     */
+    public static class Pair {
+        final String first;
+        final String second;
+
+        public Pair(String first, String second) {
+            this.first = first;
+            this.second = second;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/ClassBuilder.java	Tue Apr 24 11:54:03 2018 -0700
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2018, 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 builder;
+
+import toolbox.ToolBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Builder for type declarations.
+ * Note: this implementation does not support everything and is not
+ * exhaustive.
+ */
+public class ClassBuilder extends AbstractBuilder {
+
+    private final ToolBox tb;
+    private final String fqn;
+    private final String clsname;
+    private final String typeParameter;
+
+    private String pkg;
+    private final List<String> imports;
+
+    private String extendsType;
+    private final List<String> implementsTypes;
+    private final List<MemberBuilder> members;
+    private final List<ClassBuilder> inners;
+    private final List<ClassBuilder> nested;
+
+
+    final static Pattern CLASS_RE = Pattern.compile("(.*)(<.*>)");
+
+    /**
+     * Creates a class builder.
+     * @param tb the toolbox reference
+     * @param name the name of the type
+     */
+    public ClassBuilder(ToolBox tb, String name) {
+        super(new Modifiers(), name);
+        this.tb = tb;
+
+        Matcher m = CLASS_RE.matcher(name);
+        if (m.matches()) {
+            fqn = m.group(1);
+            typeParameter = m.group(2);
+        } else {
+            fqn = name;
+            typeParameter = null;
+        }
+        if (fqn.contains(".")) {
+            this.pkg = name.substring(0, fqn.lastIndexOf('.'));
+            clsname = fqn.substring(fqn.lastIndexOf('.') + 1);
+        } else {
+            clsname = fqn;
+        }
+        imports = new ArrayList<>();
+        implementsTypes = new ArrayList<>();
+        members = new ArrayList<>();
+        nested = new ArrayList<>();
+        inners = new ArrayList<>();
+    }
+
+    /**
+     * Adds an import(s).
+     * @param i the import type.
+     * @return this builder.
+     */
+    public ClassBuilder addImports(String i) {
+        imports.add(i);
+        return this;
+    }
+
+    /**
+     * Sets the modifiers for this builder.
+     * @param modifiers the modifiers
+     * @return this builder
+     */
+    public ClassBuilder setModifiers(String... modifiers) {
+        this.modifiers.setModifiers(modifiers);
+        return this;
+    }
+
+    /**
+     * Sets the enclosing type's name.
+     *
+     * @param className the enclosing type's name
+     */
+    @Override
+    void setClassName(String className) {
+        cname = className;
+    }
+
+    /**
+     * Sets a comment for the element.
+     *
+     * @param comments for the element
+     * @return this builder.
+     */
+    @Override
+    public ClassBuilder setComments(String... comments) {
+        super.setComments(comments);
+        return this;
+    }
+
+    /**
+     * Sets a comment for the element. Typically used to set
+     * the user's preferences whether an automatic comment is
+     * required or no API comment.
+     *
+     * @param kind of comment, automatic or no comment.
+     * @return this builder.
+     */
+    @Override
+    public ClassBuilder setComments(Comment.Kind kind) {
+        super.setComments(kind);
+        return this;
+    }
+
+    /**
+     * Set the super-type of the type.
+     * @param name of the super type.
+     * @return this builder.
+     */
+    public ClassBuilder setExtends(String name) {
+        extendsType = name;
+        return this;
+    }
+
+    /**
+     * Adds an implements declaration(s).
+     * @param names the interfaces
+     * @return this builder.
+     */
+    public ClassBuilder addImplements(String... names) {
+        implementsTypes.addAll(List.of(names));
+        return this;
+    }
+
+    /**
+     * Adds a member(s) to the class declaration.
+     * @param mbs the member builder(s) representing member(s).
+     * @return this builder
+     */
+    public ClassBuilder addMembers(MemberBuilder... mbs) {
+        for (MemberBuilder mb : mbs) {
+            members.add(mb);
+            mb.setClassName(fqn);
+        }
+        return this;
+    }
+
+    /**
+     * Adds nested-classes, to an outer class to an outer builder.
+     * @param cbs class builder(s) of the nested classes.
+     * @return this builder.
+     */
+    public ClassBuilder addNestedClasses(ClassBuilder... cbs) {
+        Stream.of(cbs).forEach(cb -> {
+            nested.add(cb);
+            cb.setClassName(fqn);
+        });
+        return this;
+    }
+
+    /**
+     * Adds inner-classes, to an an outer class builder.
+     * @param cbs class builder(s) of the inner classes.
+     * @return this builder.
+     */
+    public ClassBuilder addInnerClasses(ClassBuilder... cbs) {
+        Stream.of(cbs).forEach(cb -> {
+            inners.add(cb);
+            cb.setClassName(fqn);
+        });
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        OutputWriter ow = new OutputWriter();
+        if (pkg != null)
+            ow.println("package " + pkg + ";");
+        imports.forEach(i -> ow.println("import " + i + ";"));
+        switch (comments.kind) {
+            case AUTO:
+                ow.println("/** Class " + fqn + " */");
+                break;
+            case USER:
+                ow.println("/** ");
+                comments.comments.forEach(c -> ow.println(" * " + c));
+                ow.println(" */");
+                break;
+            case NO_API_COMMENT:
+                ow.println("// NO_API_COMMENT");
+                break;
+        }
+        ow.print(modifiers.toString());
+        ow.print(clsname);
+        if (typeParameter != null) {
+            ow.print(typeParameter + " ");
+        } else {
+            ow.print(" ");
+        }
+        if (extendsType != null && !extendsType.isEmpty()) {
+            ow.print("extends " + extendsType + " ");
+        }
+        if (!implementsTypes.isEmpty()) {
+            ow.print("implements ");
+
+            ListIterator<String> iter = implementsTypes.listIterator();
+            while (iter.hasNext()) {
+                String s = iter.next() ;
+                ow.print(s);
+                if (iter.hasNext())
+                    ow.print(", ");
+            }
+        }
+        ow.print("{");
+        if (!nested.isEmpty()) {
+            ow.println("");
+            nested.forEach(m -> ow.println(m.toString()));
+        }
+
+        if (!members.isEmpty()) {
+            ow.println("");
+            members.forEach(m -> ow.println(m.toString()));
+        }
+
+        ow.println("}");
+        if (!inners.isEmpty()) {
+            ow.println(" {");
+            inners.forEach(m -> ow.println(m.toString()));
+            ow.println("}");
+        }
+        return ow.toString();
+    }
+
+    /**
+     * Writes out the java source for a type element. Package directories
+     * will be created as needed as inferred by the type name.
+     * @param srcDir the top level source directory.
+     * @throws IOException if an error occurs.
+     */
+    public void write(Path srcDir) throws IOException {
+        Files.createDirectories(srcDir);
+        Path outDir = srcDir;
+        if (pkg != null && !pkg.isEmpty()) {
+            String pdir = pkg.replace(".", "/");
+            outDir = Paths.get(srcDir.toString(), pdir);
+            Files.createDirectories(outDir);
+        }
+        Path filePath = Paths.get(outDir.toString(), clsname + ".java");
+        tb.writeFile(filePath, this.toString());
+    }
+
+    /**
+     * The member builder, this is the base class for all types of members.
+     */
+    public static abstract class MemberBuilder extends AbstractBuilder {
+        public MemberBuilder(Modifiers modifiers, String name) {
+            super(modifiers, name);
+        }
+
+        /**
+         * Sets the enclosing type's name.
+         * @param className the enclosing type's name
+         */
+        @Override
+        void setClassName(String className) {
+            cname = className;
+        }
+
+        /**
+         * Sets a comment for the element.
+         *
+         * @param comments for any element
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setComments(String... comments) {
+            super.setComments(comments);
+            return this;
+        }
+
+        /**
+         * Sets a comment for the element. Typically used to set user's
+         * preferences whether an automatic comment is required or no API
+         * comment.
+         *
+         * @param kind of comment, automatic or no comment.
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setComments(Comment.Kind kind) {
+            super.setComments(kind);
+            return this;
+        }
+
+        /**
+         * Sets a new modifier.
+         *
+         * @param modifiers
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setModifiers(String... modifiers) {
+            super.setModifiers(modifiers);
+            return this;
+        }
+    }
+
+    /**
+     * The field builder.
+     */
+    public static class FieldBuilder extends MemberBuilder {
+        private String fieldType;
+        private String value;
+
+        private static final Pattern FIELD_RE = Pattern.compile("(.*)(\\s*=\\s*)(.*)(;)");
+
+        /**
+         * Constructs a field with the modifiers and name of the field.
+         * The builder by default is configured to auto generate the
+         * comments for the field.
+         * @param name of the field
+         */
+        public FieldBuilder(String name) {
+            super(new Modifiers(), name);
+            this.comments = new Comment(Comment.Kind.AUTO);
+        }
+
+        /**
+         * Returns a field builder by parsing the string.
+         * ex:  public static String myPlayingField;
+         * @param fieldString describing the field.
+         * @return a field builder.
+         */
+        public static FieldBuilder parse(String fieldString) {
+            String prefix;
+            String value = null;
+            Matcher m = FIELD_RE.matcher(fieldString);
+            if (m.matches()) {
+                prefix = m.group(1).trim();
+                value = m.group(3).trim();
+            } else {
+                int end = fieldString.lastIndexOf(';') > 0
+                        ? fieldString.lastIndexOf(';')
+                        : fieldString.length();
+                prefix = fieldString.substring(0, end).trim();
+            }
+            List<String> list = Stream.of(prefix.split(" "))
+                    .filter(s -> !s.isEmpty()).collect(Collectors.toList());
+            if (list.size() < 2) {
+                throw new IllegalArgumentException("incorrect field string: "
+                        + fieldString);
+            }
+            String name = list.get(list.size() - 1);
+            String fieldType = list.get(list.size() - 2);
+
+            FieldBuilder fb = new FieldBuilder(name);
+            fb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+            fb.setFieldType(fieldType);
+            if (value != null)
+                fb.setValue(value);
+
+            return fb;
+        }
+
+        /**
+         * Sets the modifiers for this builder.
+         *
+         * @param mods
+         * @return this builder
+         */
+        public FieldBuilder setModifiers(String mods) {
+            this.modifiers.setModifiers(mods);
+            return this;
+        }
+
+        /**
+         * Sets the type of the field.
+         * @param fieldType the name of the type.
+         * @return this field builder.
+         */
+        public FieldBuilder setFieldType(String fieldType) {
+            this.fieldType = fieldType;
+            return this;
+        }
+
+        public FieldBuilder setValue(String value) {
+            this.value = value;
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            String indent = "    ";
+            OutputWriter ow = new OutputWriter();
+            switch (comments.kind) {
+                case AUTO:
+                    ow.println(indent + "/** Field " +
+                            super.name + " in " + super.cname + " */");
+                    break;
+                case INHERIT_DOC: case USER:
+                    ow.println(indent + "/** " +
+                            comments.toString() + " */");
+                    break;
+                case NO_API_COMMENT:
+                    ow.println(indent + "// NO_API_COMMENT");
+                    break;
+            }
+            ow.print(indent + super.modifiers.toString() + " ");
+            ow.print(fieldType + " ");
+            ow.print(super.name);
+            if (value != null) {
+                ow.print(" = " + value);
+            }
+            ow.println(";");
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The method builder.
+     */
+    public static class MethodBuilder extends MemberBuilder {
+
+        private final List<Pair> params;
+
+        private String returnType;
+        private List<String> body;
+
+        final static Pattern METHOD_RE = Pattern.compile("(.*)(\\()(.*)(\\))(.*)");
+
+        /**
+         * Constructs a method builder. The builder by default is configured
+         * to auto generate the comments for this method.
+         * @param name of the method.
+         */
+        public MethodBuilder(String name) {
+            super(new Modifiers(), name);
+            comments = new Comment(Comment.Kind.AUTO);
+            params = new ArrayList<>();
+            body = null;
+        }
+
+        /**
+         * Returns a method builder by parsing a string which
+         * describes a method.
+         * @param methodString the method description.
+         * @return a method builder.
+         */
+        public static MethodBuilder parse(String methodString) {
+            Matcher m = METHOD_RE.matcher(methodString);
+            if (!m.matches())
+                throw new IllegalArgumentException("string does not match: "
+                        + methodString);
+            String prefix = m.group(1);
+            String params = m.group(3);
+            String suffix = m.group(5).trim();
+
+            if (prefix.length() < 2) {
+                throw new IllegalArgumentException("incorrect method string: "
+                        + methodString);
+            }
+
+            String[] pa = prefix.split(" ");
+            List<String> list = List.of(pa);
+            String name = list.get(list.size() - 1);
+            String returnType = list.get(list.size() - 2);
+
+            MethodBuilder mb = new MethodBuilder(name);
+            mb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+            mb.setReturn(returnType);
+
+            pa = params.split(",");
+            Stream.of(pa).forEach(p -> {
+                p = p.trim();
+                if (!p.isEmpty())
+                    mb.addParameter(p);
+            });
+            if (!suffix.isEmpty() || suffix.length() > 1) {
+                mb.setBody(suffix);
+            }
+            return mb;
+        }
+
+        /**
+         * Sets the modifiers for this builder.
+         *
+         * @param modifiers
+         * @return this builder
+         */
+        public MethodBuilder setModifiers(String modifiers) {
+            this.modifiers.setModifiers(modifiers);
+            return this;
+        }
+
+        @Override
+        public MethodBuilder setComments(String... comments) {
+            super.setComments(comments);
+            return this;
+        }
+
+        @Override
+        public MethodBuilder setComments(Comment.Kind kind) {
+            super.setComments(kind);
+            return this;
+        }
+
+        /**
+         * Sets a return type for a method.
+         * @param returnType the return type.
+         * @return this method builder.
+         */
+        public MethodBuilder setReturn(String returnType) {
+            this.returnType = returnType;
+            return this;
+        }
+
+        /**
+         * Adds a parameter(s) to the method method builder.
+         * @param params a pair consisting of type and parameter name.
+         * @return this method builder.
+         */
+        public MethodBuilder addParameters(Pair... params) {
+            this.params.addAll(List.of(params));
+            return this;
+        }
+
+        /**
+         * Adds a parameter to the method method builder.
+         * @param type the type of parameter.
+         * @param name the parameter name.
+         * @return this method builder.
+         */
+        public MethodBuilder addParameter(String type, String name) {
+            this.params.add(new Pair(type, name));
+            return this;
+        }
+
+        /**
+         * Adds a parameter to the method builder, by parsing the string.
+         * @param s the parameter description such as "Double voltage"
+         * @return this method builder.
+         */
+        public MethodBuilder addParameter(String s) {
+            String[] p = s.trim().split(" ");
+            return addParameter(p[0], p[p.length - 1]);
+        }
+
+        /**
+         * Sets the body of the method, described by the string.
+         * Such as "{", "double i = v/r;", "return i;", "}"
+         * @param body of the methods
+         * @return
+         */
+        public MethodBuilder setBody(String... body) {
+            if (body == null) {
+                this.body = null;
+            } else {
+                this.body = new ArrayList<>();
+                this.body.addAll(List.of(body));
+            }
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            OutputWriter ow = new OutputWriter();
+            String indent = "    ";
+            switch (comments.kind) {
+                case AUTO:
+                    ow.println(indent + "/** Method " + super.name + " in " + super.cname);
+                    if (!params.isEmpty())
+                        params.forEach(p -> ow.println(indent + " * @param " + p.second + " a param"));
+                    if (returnType != null && !returnType.isEmpty() && !returnType.contains("void"))
+                        ow.println(indent + " * @return returns something");
+                    ow.println(indent + " */");
+                    break;
+                case INHERIT_DOC: case USER:
+                    ow.println(indent + "/** " + comments.toString() + " */");
+                    break;
+                case NO_API_COMMENT:
+                    ow.println(indent + "// NO_API_COMMENT");
+                    break;
+            }
+
+            ow.print(indent + super.modifiers.toString() + " ");
+            ow.print(returnType + " ");
+            ow.print(super.name + "(");
+            if (!params.isEmpty()) {
+                ListIterator<Pair> iter = params.listIterator();
+                while (iter.hasNext()) {
+                    Pair p = iter.next();
+                    ow.print(p.first + " " + p.second);
+                    if (iter.hasNext())
+                        ow.print(", ");
+                }
+            }
+            ow.print(")");
+            if (body == null) {
+                ow.println(";");
+            } else {
+                body.forEach(ow::println);
+            }
+            return ow.toString();
+        }
+    }
+
+//A sample, to test with an IDE.
+//    public static void main(String... args) throws IOException {
+//        ClassBuilder cb = new ClassBuilder(new ToolBox(), "foo.bar.Test<C extends A>");
+//        cb.addModifiers("public", "abstract", "static")
+//                .addImports("java.io").addImports("java.nio")
+//                .setComments("A comment")
+//                .addImplements("Serialization", "Something")
+//                .setExtends("java.lang.Object")
+//                .addMembers(
+//                        FieldBuilder.parse("public int xxx;"),
+//                        FieldBuilder.parse("public int yyy = 10;"),
+//                        MethodBuilder.parse("public static void main(A a, B b, C c);")
+//                            .setComments("CC"),
+//                        MethodBuilder.parse("void foo(){//do something}")
+//
+//                );
+//        ClassBuilder ic = new ClassBuilder(new ToolBox(), "IC");
+//        cb.addModifiers( "interface");
+//        cb.addNestedClasses(ic);
+//        System.out.println(cb.toString());
+//        cb.write(Paths.get("src-out"));
+//    }
+}