All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.redhat.ceylon.ceylondoc.ClassDoc Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
/*
 * Copyright Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the authors tag. All rights reserved.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License version 2.
 * 
 * This particular file is subject to the "Classpath" exception as provided in the 
 * LICENSE file that accompanied this code.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package com.redhat.ceylon.ceylondoc;

import static com.redhat.ceylon.ceylondoc.Util.getAncestors;
import static com.redhat.ceylon.ceylondoc.Util.getDoc;
import static com.redhat.ceylon.ceylondoc.Util.getSuperInterfaces;
import static com.redhat.ceylon.ceylondoc.Util.isAbbreviatedType;
import static com.redhat.ceylon.ceylondoc.Util.isEmpty;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import com.redhat.ceylon.ceylondoc.Util.ReferenceableComparatorByName;
import com.redhat.ceylon.model.typechecker.model.Class;
import com.redhat.ceylon.model.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Function;
import com.redhat.ceylon.model.typechecker.model.Interface;
import com.redhat.ceylon.model.typechecker.model.ModelUtil;
import com.redhat.ceylon.model.typechecker.model.Package;
import com.redhat.ceylon.model.typechecker.model.Parameter;
import com.redhat.ceylon.model.typechecker.model.ParameterList;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.TypeAlias;
import com.redhat.ceylon.model.typechecker.model.TypeDeclaration;
import com.redhat.ceylon.model.typechecker.model.TypedDeclaration;
import com.redhat.ceylon.model.typechecker.model.Value;

public class ClassDoc extends ClassOrPackageDoc {

    private TypeDeclaration klass;
    private SortedMap constructors;
    private SortedMap> methods;
    private SortedMap attributes;
    private SortedMap innerInterfaces;
    private SortedMap innerClasses;
    private SortedMap innerExceptions;
    private SortedMap innerAliases;
    private List superInterfaces;
    private List superClasses;
    private Map>> superclassInheritedMembers = new HashMap>>(2);
    private Map>> interfaceInheritedMembers = new HashMap>>(2);

    private interface MemberSpecification {
        boolean isSatisfiedBy(Declaration decl);
    }

    private MemberSpecification attributeSpecification = new MemberSpecification() {
        @Override
        public boolean isSatisfiedBy(Declaration decl) {
            return decl instanceof Value;
        }
    };

    private MemberSpecification methodSpecification = new MemberSpecification() {
        @Override
        public boolean isSatisfiedBy(Declaration decl) {
            return decl instanceof Function;
        }
    };
    
    private Comparator overloadedFunctionComperator = new Comparator() {

        @Override
        public int compare(Function f1, Function f2) {
            int result;
            
            List parameterLists1 = f1.getParameterLists();
            List parameterLists2 = f2.getParameterLists();
            
            result = Integer.compare(parameterLists1.size(), parameterLists2.size());
            if( result != 0 ) {
                return result;
            }
            
            for( int i = 0; i < parameterLists1.size(); i++) {
                List parameterList1 = parameterLists1.get(i).getParameters();
                List parameterList2 = parameterLists2.get(i).getParameters();

                result = Integer.compare(parameterList1.size(), parameterList2.size());
                if( result != 0 ) {
                    return result;
                }
            }
            
            String signature1 = f1.toString();
            String signature2 = f2.toString();
            
            result = signature1.compareTo(signature2);
            
            return result;
        }

    };

    public ClassDoc(CeylonDocTool tool, Writer writer, TypeDeclaration klass) throws IOException {
        super(tool.getModule(klass), tool, writer);
        this.klass = klass;
        loadMembers();
    }

    private void loadMembers() {
        constructors = new TreeMap();
        methods = new TreeMap>();
        attributes = new TreeMap();
        innerInterfaces = new TreeMap();
        innerClasses = new TreeMap();
        innerExceptions = new TreeMap();
        innerAliases = new TreeMap();
        superClasses = getAncestors(klass);
        superInterfaces = getSuperInterfaces(klass);
        
        for (Declaration m : klass.getMembers()) {
            if (tool.shouldInclude(m)) {
                if (ModelUtil.isConstructor(m)) {
                    addTo(constructors, m);
                } else if (m instanceof Value) {
                    addTo(attributes, (Value)m);
                } else if (m instanceof Function) {
                    if( m.isAbstraction() && m.getOverloads().size() > 0 ) {
                        // we want document each overloads, see https://github.com/ceylon/ceylon/issues/5748
                        continue;
                    }
                    addTo(methods, (Function)m);
                } else if (m instanceof Interface) {
                    addTo(innerInterfaces, (Interface)m);
                } else if (m instanceof Class) {
                    Class c = (Class) m;
                    if (Util.isThrowable(c)) {
                        addTo(innerExceptions, c);
                    } else {
                        addTo(innerClasses, c);
                    }
                } else if (m instanceof TypeAlias) {
                    addTo(innerAliases, (TypeAlias)m);
                }
            }
        }

        Collections.sort(superInterfaces, ReferenceableComparatorByName.INSTANCE);
        
        loadInheritedMembers(attributeSpecification, superClasses, superclassInheritedMembers);
        loadInheritedMembers(methodSpecification, superClasses, superclassInheritedMembers);
        loadInheritedMembers(attributeSpecification, superInterfaces, interfaceInheritedMembers);
        loadInheritedMembers(methodSpecification, superInterfaces, interfaceInheritedMembers);
    }

    private  void addTo(SortedMap map, T decl) {
        map.put(Util.getDeclarationName(decl), decl);
        for(String alias : decl.getAliases()){
            map.put(alias, decl);
        }
    }
    
    private void addTo(SortedMap> map, Function decl) {
        String declName = Util.getDeclarationName(decl);
        SortedSet overloadedDeclSet = map.get(declName);
        if( overloadedDeclSet == null ) {
            overloadedDeclSet = new TreeSet(overloadedFunctionComperator);
            map.put(declName, overloadedDeclSet);
        }
        overloadedDeclSet.add(decl);
        
        for(String alias : decl.getAliases()){
            overloadedDeclSet = map.get(alias);
            if( overloadedDeclSet == null ) {
                overloadedDeclSet = new TreeSet(overloadedFunctionComperator);
                map.put(alias, overloadedDeclSet);
            }
            overloadedDeclSet.add(decl);
        }
    }

    private void loadInheritedMembers(MemberSpecification specification, 
            List superClassOrInterfaceList, 
            Map>> superClassOrInterfaceInheritedMemebers) {
        LinkedHashMap> inheritedMembersMap = 
                new LinkedHashMap>();
        for (TypeDeclaration superClassOrInterface : superClassOrInterfaceList) {
            SortedMap inheritedMembers = new TreeMap();
            for (Declaration member : superClassOrInterface.getMembers()) {
                if (specification.isSatisfiedBy(member) && tool.shouldInclude(member) ) {
                    inheritedMembers.put(Util.getDeclarationName(member), member);
                    for(String alias : member.getAliases()){
                        inheritedMembers.put(alias, member);
                    }
                }
            }
            if( !inheritedMembers.isEmpty() ) {
                inheritedMembersMap.put(superClassOrInterface, inheritedMembers);
            }
        }
        superClassOrInterfaceInheritedMemebers.put(specification, inheritedMembersMap);
    }

    private boolean isObject() {
        return klass instanceof Class && klass.isAnonymous();
    }

    private boolean hasInitializer() {
        return klass instanceof Class && !isObject() && constructors.isEmpty();
    }

    /**
     * Determines whether the type has any attributes (include any inherited from superclasses or superinterfaces). 
     * @return true if the type has any attributes.
     */
    private boolean hasAnyAttributes() {
        return !(attributes.isEmpty() 
                    && interfaceInheritedMembers.get(attributeSpecification).isEmpty()
                    && superclassInheritedMembers.get(attributeSpecification).isEmpty());
    }

    /**
     * Determines whether the type has any methods (include any inherited from superclasses or superinterfaces). 
     * @return true if the type has any methods.
     */
    private boolean hasAnyMethods() {
        return !(methods.isEmpty() 
                    && interfaceInheritedMembers.get(methodSpecification).isEmpty()
                    && superclassInheritedMembers.get(methodSpecification).isEmpty());
    }
    
    private String getClassLabel() {
        if (klass.isDynamic()) {
            return "dynamic";
        } else if (klass instanceof Interface) {
            return "interface";
        } else if (klass.isAnnotation()) {
            return "annotation";
        } else if (isObject()) {
            return "object";
        } else {
            return "class";
        }
    }

    public void generate() throws IOException {
        writeHeader(Util.capitalize(getClassLabel()) + " " + klass.getName());
        writeNavBar();
        writeSubNavBar();
        
        open("div class='container-fluid'");
        
        writeDescription();
        
        if (hasInitializer()) {
            writeInitializer((Class) klass);
        }

        if( !constructors.isEmpty() ) {
            writeConstructors();
        }
        
        if (hasAnyAttributes()) {
            open("div id='section-attributes'");
            writeAttributes();
            writeInheritedMembers(attributeSpecification, "Inherited Attributes", "Attributes inherited from: ");
            close("div");
        }

        if (hasAnyMethods()) {
            open("div id='section-methods'");
            writeMethods();
            writeInheritedMembers(methodSpecification, "Inherited Methods", "Methods inherited from: ");
            close("div");
        }

        // Nested types at the end
        writeInnerTypes(innerAliases, "section-nested-aliases", "Nested Aliases");
        writeInnerTypes(innerInterfaces, "section-nested-interfaces", "Nested Interfaces");
        writeInnerTypes(innerClasses, "section-nested-classes", "Nested Classes");
        writeInnerTypes(innerExceptions, "section-nested-exceptions", "Nested Exceptions");

        close("div");
        
        writeFooter();
    }

    private void writeSubNavBar() throws IOException {
        Package pkg = tool.getPackage(klass);
        
        open("div class='sub-navbar'");
        
        writeLinkSourceCode(klass);
        
        open("div class='sub-navbar-inner'");
        
        open("span class='sub-navbar-package'");
        writeIcon(pkg);
        writePackageNavigation(pkg);
        close("span");
        
        write("
"); writeClassSignature(); close("div"); // sub-navbar-inner open("div class='sub-navbar-menu'"); writeSubNavBarLink(linkRenderer().to(module).getUrl(), "Overview", 'O', "Jump to module documentation"); writeSubNavBarLink(linkRenderer().to(pkg).getUrl(), "Package", 'P', "Jump to package documentation"); if (hasInitializer()) { writeSubNavBarLink("#section-initializer", "Initializer", 'z', "Jump to initializer"); } if (!constructors.isEmpty()) { writeSubNavBarLink("#section-constructors", "Constructors", 't', "Jump to constructors"); } if (hasAnyAttributes()) { writeSubNavBarLink("#section-attributes", "Attributes", 'A', "Jump to attributes"); } if (hasAnyMethods()) { writeSubNavBarLink("#section-methods", "Methods", 'M', "Jump to methods"); } if (!innerAliases.isEmpty()) { writeSubNavBarLink("#section-nested-aliases", "Nested Aliases", 'l', "Jump to nested aliases"); } if (!innerInterfaces.isEmpty()) { writeSubNavBarLink("#section-nested-interfaces", "Nested Interfaces", 'I', "Jump to nested interfaces"); } if (!innerClasses.isEmpty()) { writeSubNavBarLink("#section-nested-classes", "Nested Classes", 'C', "Jump to nested classes"); } if (!innerExceptions.isEmpty()) { writeSubNavBarLink("#section-nested-exceptions", "Nested Exceptions", 'E', "Jump to nested exceptions"); } if( isObject() ) { writeSubNavBarLink(linkRenderer().to(klass.getContainer()).useAnchor(klass.getName()).getUrl(), "Singleton object declaration", '\0', "Jump to singleton object declaration"); } close("div"); // sub-navbar-menu close("div"); // sub-navbar } private void writeClassSignature() throws IOException { open("span class='sub-navbar-label'"); write(getClassLabel()); close("span"); writeIcon(klass); open("span class='sub-navbar-name'"); writeQualifyingType(klass); open("span class='type-identifier'"); write(klass.getName()); close("span"); writeTypeParameters(klass.getTypeParameters(), klass); close("span"); writeInheritance(klass); writeTypeParametersConstraints(klass.getTypeParameters(), klass); } private void writeQualifyingType(TypeDeclaration klass) throws IOException { if (klass.isClassOrInterfaceMember()) { TypeDeclaration container = (TypeDeclaration) klass.getContainer(); writeQualifyingType(container); linkRenderer().to(container).useScope(klass).write(); write("."); } } private void writeDescription() throws IOException { open("div class='class-description'"); writeTagged(klass); writeTabs(); close("div"); // class-description } private void writeTabs() throws IOException { boolean hasTypeHierarchy = klass instanceof Class; boolean hasSupertypeHierarchy = klass instanceof Class || !isEmpty(klass.getSatisfiedTypes()); boolean hasSubtypeHierarchy = !isEmpty(tool.getSubclasses(klass)) || !isEmpty(tool.getSatisfyingClassesOrInterfaces(klass)); open("div class='type-tabs section'"); open("div class='tabbable'"); open("ul class='nav nav-tabs'"); writeTabNav("tabDocumentation", "Documentation", "icon-documentation", true, true, false); writeTabNav("tabTypeHierarchy", "Type Hierarchy", "icon-type-hierarchy", false, hasTypeHierarchy, false); writeTabNav("tabSupertypeHierarchy", "Supertype Hierarchy", "icon-supertype-hierarchy", false, hasSupertypeHierarchy, false); writeTabNav("tabSubtypeHierarchy", "Subtype Hierarchy", "icon-subtype-hierarchy", false, hasSubtypeHierarchy, Util.isEnumerated(klass)); close("ul"); // nav-tabs open("div class='tab-content'"); open("div class='tab-pane active' id='tabDocumentation'"); /*if (!klass.getUnit().getAnythingDeclaration().equals(klass) && klass.getExtendedTypeDeclaration()!=null) { writeListOnSummary("extended", "Extended class: ", singletonList(klass.getExtendedTypeDeclaration())); } writeListOnSummary("satisfied", "Satisfied Interfaces: ", superInterfaces); writeEnclosingType();*/ writeAnnotationConstructors(); around("div class='doc'", getDoc(klass, linkRenderer())); writeBy(klass); writeSee(klass); close("div"); open("div class='tab-pane' id='tabTypeHierarchy'"); if( hasTypeHierarchy ) { writeTypeHierarchy(); } else { write("

no type hierarchy

"); } close("div"); open("div class='tab-pane' id='tabSupertypeHierarchy'"); if( hasSupertypeHierarchy ) { writeSuperTypeHierarchy(Collections.singletonList(klass), 0); } else { write("

no supertypes hierarchy

"); } close("div"); open("div class='tab-pane' id='tabSubtypeHierarchy'"); if( hasSubtypeHierarchy ) { writeSubtypesHierarchy(Collections.singletonList(klass), 0); } else { write("

no subtypes hierarchy

"); } close("div"); close("div"); // tab-content close("div"); // tabbable close("div"); // typeHierarchy } private void writeTabNav(String id, String name, String icon, boolean isActive, boolean isEnabled, boolean isEnumerated) throws IOException { write(""); write(""); write(""); if(isEnumerated){ around("span class='label label-info' title='Enumerated type with an "of" clause'", "Enumerated"); write(" "); } write("" + name + ""); write(""); write(""); } private void writeTypeHierarchy() throws IOException { LinkedList superTypes = new LinkedList(); superTypes.add(klass.getType()); Type type = klass.getExtendedType(); while (type != null) { superTypes.add(0, type); type = type.getExtendedType(); } int level = 0; for (Type superType : superTypes) { writeTypeHierarchyLevel(superType.getDeclaration(), level < superTypes.size() - 1); if (!isEmpty(superType.getSatisfiedTypes())) { write(" ...and other supertypes"); } open("div class='subhierarchy'"); level++; } while (level-- > 0) { close("div"); // subhierarchy close("li", "ul"); } } private void writeSuperTypeHierarchy(List types, int level) throws IOException { if (types.size() > 1) { Collections.sort(types, ReferenceableComparatorByName.INSTANCE); } for (TypeDeclaration type : types) { List supertypes = collectSupertypes(type); writeTypeHierarchyLevel(type, !supertypes.isEmpty()); open("div class='subhierarchy'"); writeSuperTypeHierarchy(supertypes, level + 1); close("div"); // subhierarchy close("li", "ul"); } } private void writeSubtypesHierarchy(List types, int level) throws IOException { if (types.size() > 1) { Collections.sort(types, ReferenceableComparatorByName.INSTANCE); } for (TypeDeclaration type : types) { List subtypes = collectSubtypes(type); writeTypeHierarchyLevel(type, !subtypes.isEmpty()); if(level == 0 && Util.isEnumerated(type)){ around("span class='keyword'", " of"); } open("div class='subhierarchy'"); writeSubtypesHierarchy(subtypes, level + 1); close("div"); // subhierarchy close("li", "ul"); } } private void writeTypeHierarchyLevel(TypeDeclaration type, boolean hasSublevels) throws IOException { open("ul class='hierarchy-level'", "li"); if( hasSublevels ) { write(""); } else { write(""); } writeIcon(type); linkRenderer().to(type).useScope(klass).withinText(true).printTypeParameters(false).printAbbreviated(false).write(); } private List collectSupertypes(TypeDeclaration type) { List supertypes = new ArrayList(); if (type instanceof Class && type.getExtendedType() != null) { supertypes.add(type.getExtendedType().getDeclaration()); } List satisfiedTypes = type.getSatisfiedTypes(); if (satisfiedTypes != null) { for (Type satisfiedType: satisfiedTypes) { supertypes.add(satisfiedType.getDeclaration()); } } return supertypes; } private List collectSubtypes(TypeDeclaration type) { List subtypes = new ArrayList(); List subclasses = tool.getSubclasses(type); if (subclasses != null) { subtypes.addAll(subclasses); } List satisfyingClassesOrInterfaces = tool.getSatisfyingClassesOrInterfaces(type); if (satisfyingClassesOrInterfaces != null) { subtypes.addAll(satisfyingClassesOrInterfaces); } return subtypes; } private void writeListOnSummary(String cssClass, String title, List types) throws IOException { if (!isEmpty(types)) { open("div class='" + cssClass + " section'"); around("span class='title'", title); boolean first = true; for (Object type : types) { if (!first) { write(", "); } else { first = false; } if( type instanceof TypedDeclaration ) { TypedDeclaration decl = (TypedDeclaration) type; linkRenderer().to(decl).useScope(klass).write(); } else if( type instanceof ClassOrInterface ) { ClassOrInterface coi = (ClassOrInterface) type; linkRenderer().to(coi).useScope(klass).printAbbreviated(!isAbbreviatedType(coi)).write(); } else { Type pt = (Type) type; linkRenderer().to(pt).useScope(klass).printAbbreviated(!isAbbreviatedType(pt.getDeclaration())).write(); } } close("div"); } } /*private void writeEnclosingType() throws IOException { if (klass.isMember()) { ClassOrInterface enclosingType = (ClassOrInterface) klass.getContainer(); open("div class='enclosingType section'"); around("span class='title'", "Enclosing " + (enclosingType instanceof Class ? "class: " : "interface: ")); writeIcon(enclosingType); linkToDeclaration(enclosingType); close("div"); } }*/ private void writeAnnotationConstructors() throws IOException { if( klass.isAnnotation() ) { List annotationConstructors = tool.getAnnotationConstructors(klass); if( annotationConstructors != null ) { Collections.sort(annotationConstructors, ReferenceableComparatorByName.INSTANCE); writeListOnSummary("annotationConstructors", "Annotation Constructors: ", annotationConstructors); } } } private void writeInheritedMembers(MemberSpecification specification, String tableTitle, String rowTitle) throws IOException { boolean first = true; Map> superClassInheritedMembersMap = superclassInheritedMembers.get(specification); List superClasses = new ArrayList(superclassInheritedMembers.get(specification).keySet()); Collections.sort(superClasses, ReferenceableComparatorByName.INSTANCE); for (TypeDeclaration superClass : superClasses) { SortedMap inheritedMembers = superClassInheritedMembersMap.get(superClass); if (first) { first = false; openTable(null, tableTitle, 1, false); } writeInheritedMembersRow(rowTitle, superClass, inheritedMembers); } Map> superInterfaceInheritedMembersMap = interfaceInheritedMembers.get(specification); List superInterfaces = new ArrayList(superInterfaceInheritedMembersMap.keySet()); Collections.sort(superInterfaces, ReferenceableComparatorByName.INSTANCE); for (TypeDeclaration superInterface : superInterfaces) { SortedMap members = superInterfaceInheritedMembersMap.get(superInterface); if (members == null || members.isEmpty()) { continue; } if (first) { first = false; openTable(null, tableTitle, 1, false); } writeInheritedMembersRow(rowTitle, superInterface, members); } if (!first) { closeTable(); } } private void writeInheritedMembersRow(String title, TypeDeclaration superType, SortedMap members) throws IOException { open("tr", "td"); write(title); writeIcon(superType); linkRenderer().to(superType).useScope(klass).withinText(true).write(); open("div class='inherited-members'"); boolean first = true; for (Entry entry : members.entrySet()) { if (!first) { write(", "); } else { first = false; } String name = entry.getKey(); Declaration member = entry.getValue(); boolean alias = Util.nullSafeCompare(name, Util.getDeclarationName(member)) != 0; LinkRenderer linkRenderer = linkRenderer().withinText(true).to(member).useScope(klass).printMemberContainerName(false); if(alias){ StringBuilder sb = new StringBuilder(); sb.append(""); sb.append(name); sb.append(""); linkRenderer.useCustomText(sb.toString()); } linkRenderer.write(); } close("div"); close("td", "tr"); } private void writeInnerTypes(Map innerTypeDeclarations, String id, String title) throws IOException { if (!innerTypeDeclarations.isEmpty()) { openTable(id, title, 2, true); for (Entry entry : innerTypeDeclarations.entrySet()) { TypeDeclaration innerTypeDeclaration = entry.getValue(); String name = entry.getKey(); if (innerTypeDeclaration instanceof ClassOrInterface) { ClassOrInterface innerClassOrInterface = (ClassOrInterface) innerTypeDeclaration; tool.doc(innerClassOrInterface); doc(name, innerClassOrInterface); } if (innerTypeDeclaration instanceof TypeAlias) { TypeAlias innerAlias = (TypeAlias) innerTypeDeclaration; doc(name, innerAlias); } } closeTable(); } } private void writeInitializer(Class klass) throws IOException { openTable("section-initializer", "Initializer", 1, true); open("tr", "td"); writeParameterLinksIfRequired(klass); writeIcon(klass); open("code class='decl-label'"); write(klass.getName()); writeParameterList(klass, klass); close("code"); open("div class='description'"); writeParameters(klass); writeThrows(klass); close("div"); close("td", "tr"); closeTable(); } private void writeConstructors() throws IOException { if (constructors.isEmpty()){ return; } openTable("section-constructors", "Constructors", 2, true); for (Entry entry : constructors.entrySet()) { doc(entry.getKey(), entry.getValue()); } closeTable(); } private void writeAttributes() throws IOException { if (attributes.isEmpty()){ return; } openTable(null, "Attributes", 2, true); for (Entry entry : attributes.entrySet()) { doc(entry.getKey(), entry.getValue()); } closeTable(); } private void writeMethods() throws IOException { if (methods.isEmpty()){ return; } openTable(null, "Methods", 2, true); for (Entry> entry : methods.entrySet()) { int index = 1; for(Function f : entry.getValue()) { String id = null; if( index > 1 ) { id = entry.getKey()+"_"+index; } doc(id, entry.getKey(), f); index++; } } closeTable(); } @Override protected void registerAdditionalKeyboardShortcuts() throws IOException { registerKeyboardShortcut('p', "index.html"); if (hasAnyAttributes()) { registerKeyboardShortcut('a', "#section-attributes"); } if (hasInitializer()) { registerKeyboardShortcut('z', "#section-initializer"); } if (!constructors.isEmpty()) { registerKeyboardShortcut('t', "#section-constructors"); } if (hasAnyMethods()) { registerKeyboardShortcut('m', "#section-methods"); } if (!innerAliases.isEmpty()) { registerKeyboardShortcut('l', "#section-nested-aliases"); } if (!innerInterfaces.isEmpty()) { registerKeyboardShortcut('i', "#section-nested-interfaces"); } if (!innerClasses.isEmpty()) { registerKeyboardShortcut('c', "#section-nested-classes"); } if (!innerExceptions.isEmpty()) { registerKeyboardShortcut('e', "#section-nested-exceptions"); } } @Override protected Object getFromObject() { return klass; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy