Package com.redhat.ceylon.ceylondoc

Source Code of com.redhat.ceylon.ceylondoc.CeylonDoc$WriteAnnotationsVisitor

/*
* 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 java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.redhat.ceylon.compiler.loader.AbstractModelLoader;
import com.redhat.ceylon.compiler.typechecker.model.Annotation;
import com.redhat.ceylon.compiler.typechecker.model.Class;
import com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.compiler.typechecker.model.Declaration;
import com.redhat.ceylon.compiler.typechecker.model.Interface;
import com.redhat.ceylon.compiler.typechecker.model.Module;
import com.redhat.ceylon.compiler.typechecker.model.ModuleImport;
import com.redhat.ceylon.compiler.typechecker.model.NothingType;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.compiler.typechecker.model.Referenceable;
import com.redhat.ceylon.compiler.typechecker.model.TypeAlias;
import com.redhat.ceylon.compiler.typechecker.model.TypedDeclaration;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

public abstract class CeylonDoc extends Markup {

    protected final CeylonDocTool tool;
    protected final Module module;
    protected final Map<Character, String> keyboardShortcuts = new HashMap<Character, String>();

    public CeylonDoc(Module module, CeylonDocTool tool, Writer writer) {
        super(writer);
        this.module = module;
        this.tool = tool;
    }
   
    protected final LinkRenderer linkRenderer() {
        return new LinkRenderer(tool, writer, getFromObject());
    }

    protected final void writeHeader(String title, String... additionalCss) throws IOException {
        write("<!DOCTYPE html>");
        open("html");
        open("head");
        tag("meta charset='UTF-8'");
        around("title", title);

        tag("link href='" + linkRenderer().getResourceUrl("favicon.ico") + "' rel='shortcut icon'");
        tag("link href='" + linkRenderer().getResourceUrl("ceylon.css") + "' rel='stylesheet' type='text/css'");
        tag("link href='" + linkRenderer().getResourceUrl("bootstrap.min.css") + "' rel='stylesheet' type='text/css'");
        tag("link href='" + linkRenderer().getResourceUrl("ceylondoc.css") + "' rel='stylesheet' type='text/css'");
        tag("link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro|Inconsolata|Inconsolata:700|PT+Sans|PT+Sans:700' rel='stylesheet' type='text/css'");
       
        for (String css : additionalCss) {
            if (!css.endsWith(".css")) {
                throw new RuntimeException(CeylondMessages.msg("error.unexpectedAdditionalResource", css));
            }
            tag("link href='" + linkRenderer().getResourceUrl(css) + "' rel='stylesheet' type='text/css'");
        }
       
        close("head");
        open("body");
       
        if (!Util.isEmpty(tool.getHeader())) {
            around("header", tool.getHeader());
        }
    }

    protected final void writeFooter(String... additionalJs) throws IOException {
        open("script type='text/javascript'");
        write("var resourceBaseUrl = '" + tool.getResourceUrl(getFromObject(), "") + "'");
        close("script");
       
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("jquery-1.8.2.min.js") + "'");
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("bootstrap.min.js") + "'");
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("rainbow.min.js") + "'");
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("ceylon.js") + "'");
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("index.js") + "'");
        around("script type='text/javascript' src='" + linkRenderer().getResourceUrl("ceylondoc.js") + "'");
       
        for (String js : additionalJs) {
            if (!js.endsWith(".js")) {
                throw new RuntimeException(CeylondMessages.msg("error.unexpectedAdditionalResource", js));
            }
            around("script type='text/javascript' src='" + linkRenderer().getResourceUrl(js) + "'");
        }
       
        writeKeyboardShortcuts();
       
        if (!Util.isEmpty(tool.getFooter())) {
            around("footer", tool.getFooter());
        }
       
        close("body");
        close("html");
    }

    protected final void writeNavBar() throws IOException {
        open("div class='navbar navbar-inverse navbar-static-top'");
        open("div class='navbar-inner'");

        open("a class='module-header' href='" + linkRenderer().to(module).getUrl() + "'");
        around("i class='module-logo'");
        around("span class='module-label'", "module");
        around("span class='module-name'", module.getNameAsString());
        around("span class='module-version'", module.getVersion());
        close("a");

        open("ul class='nav pull-right'");
        write("<li class='divider-vertical' />");
        writeNavBarExpandAllCollapseAll();
        writeNavBarInfoMenu();
        close("ul"); // nav
       
        writeNavBarSearchMenu();
        writeNavBarFilterMenu();

        close("div"); // navbar-inner
        close("div"); // navbar
    }
   
    protected void writeNavBarExpandAllCollapseAll() throws IOException {
        write("<li><a class='expand-all' href='#' title='Expand All [Shortcut: + plus]'><i class='icon-expand-all'></i></a></li>");
        write("<li><a class='collapse-all' href='#' title='Collapse All [Shortcut: - minus]'><i class='icon-collapse-all'></i></a></li>");
    }
   
    protected void writeNavBarInfoMenu() throws IOException {
        open("li id='infoDropdown' class='dropdown'");
        write("<a href='#' title='Show keyboard shortcuts [Shortcut: ?]' role='button' class='dropdown-toggle' data-toggle='dropdown'><i class='icon-info'></i></a>");
        open("ul id='info-dropdown-panel' class='dropdown-menu'");
        around("h4", "Keyboard Shortcuts");
        write("<li class='divider'></li>");
       
        open("div class='row-fluid'");
       
        open("div id='info-common-shortcuts' class='span6'");
        writeKeyboardShortcutInfo("f", "Open filter by tags");
        writeKeyboardShortcutInfo("s", "Open search page");
        writeKeyboardShortcutInfo("?", "Open this information panel");
        close("div"); // info-common-shortcuts
       
        open("div id='info-expand-collapse-shortcuts' class='span6'");
        writeKeyboardShortcutInfo("+", "Expand all");
        writeKeyboardShortcutInfo("-", "Collapse all");
        close("div"); // info-expand-collapse-shortcuts
       
        close("div"); // row-fluid
        write("<li class='divider'></li>");
        open("div class='row-fluid'");
       
        open("div id='info-doc-shortcuts' class='span6'");
        around("h5","Documentation:");
        writeKeyboardShortcutInfo("o", "Jump to module documentation");
        writeKeyboardShortcutInfo("p", "Jump to package documentation");
        writeKeyboardShortcutInfo("l", "Jump to aliases");
        writeKeyboardShortcutInfo("n", "Jump to annotations");
        writeKeyboardShortcutInfo("z", "Jump to initializer");
        if( getFromObject() instanceof Module || getFromObject() instanceof Package ) {
            writeKeyboardShortcutInfo("v", "Jump to values");
            writeKeyboardShortcutInfo("f", "Jump to functions");
        } else {
            writeKeyboardShortcutInfo("a", "Jump to attributes");
            writeKeyboardShortcutInfo("m", "Jump to methods");
        }
        writeKeyboardShortcutInfo("i", "Jump to interfaces");
        writeKeyboardShortcutInfo("c", "Jump to classes");
        writeKeyboardShortcutInfo("e", "Jump to exceptions");
        close("div"); // info-doc-shortcuts
       
        open("div id='info-search-shortcuts' class='span6'");
        around("h5", "Search page:");
        writeKeyboardShortcutInfo("enter", "Jump to selected declaration");
        writeKeyboardShortcutInfo("esc", "Clear search query/Go to overview");
        writeKeyboardShortcutInfo("up", "Move selection up");
        writeKeyboardShortcutInfo("down", "Move selection down");
        close("div"); // info-search-shortcuts
       
        close("div"); // row-fluid
        close("ul"); // dropdown-menu
        close("li"); // dropdown
    }

    private void writeKeyboardShortcutInfo(String key, String info) throws IOException {
        open("div id='"+key+"'");
        around("span class='key badge'", key);
        around("span class='info muted'", info);
        close("div");
    }

    protected void writeNavBarSearchMenu() throws IOException {
        open("ul class='nav pull-right'");
        write("<li class='divider-vertical' />");
        write("<li><a href='" + linkRenderer().getResourceUrl("../search.html") + "' title='Search this module [Shortcut: S]'><i class='icon-search'></i>Search</a></li>");
        close("ul");
    }
   
    protected void writeNavBarFilterMenu() throws IOException {
        open("ul class='nav pull-right'");
        write("<li class='divider-vertical' />");
        open("li id='filterDropdown' class='dropdown'");
        write("<a href='#' title='Filter declarations by tags [Shortcut: F]' role='button' class='dropdown-toggle' data-toggle='dropdown'><i class='icon-filter'></i>Filter <span id='filterDropdownLinkInfo'></span> <b class='caret'></b></a>");
        open("ul id='filterDropdownPanel' class='dropdown-menu'");
        around("h4 id='filterDropdownPanelInfo'", "Filter declarations by tags");
        write("<li class='divider'></li>");
       
        write("<div id='filterDropdownPanelTags'></div>");
        write("<li class='divider'></li>");
        open("div id='filterActions'");
        write("<a id='filterActionAll'>All</a>");
        write("<a id='filterActionNone'>None</a>");
        write("<a id='filterActionMore'>Show more</a>");
        close("div"); // filterActions
        close("ul"); // filterDropdownPanel
        close("li"); // filterDropdown
        close("ul"); // nav       
    }

    protected final void writeSubNavBarLink(String href, String text, char key, String tooltip) throws IOException {
        open("a href='" + href + "'");
       
        int index = text.indexOf(key);
        if( index == -1 ) {
            write("<span title='", tooltip, "'>", text, "</span>");
        } else {
            String before = text.substring(0, index);
            String after = text.substring(index+1);

            write("<span title='", tooltip, " [Shortcut: ", String.valueOf(key), "]'>");
            write(before, "<span class='accesskey'>", String.valueOf(key), "</span>", after, "</span>");
        }
       
        close("a");
    }

    protected void writeKeyboardShortcuts() throws IOException{
        registerKeyboardShortcut('s', linkRenderer().getResourceUrl("../search.html"));
        registerKeyboardShortcut('o', linkRenderer().getResourceUrl("../index.html"));
        registerAdditionalKeyboardShortcuts();
       
        if( !keyboardShortcuts.isEmpty() ) {
            open("script type='text/javascript'");
            write("jQuery('html').keypress(function(evt){\n");
            write("  evt = evt || window.event;\n");
            write("  var keyCode = evt.keyCode || evt.which;\n");
           
            write("  if( !evt.ctrlKey && !evt.altKey ) {\n");
            write("    if (keyCode == " + (int)'?' + ") {\n");
            write("      $('#infoDropdown > .dropdown-toggle').click();\n");
            write("    }\n");
            for(Map.Entry<Character, String> keyboardShortcut : keyboardShortcuts.entrySet()) {
                write("    if(keyCode == "+(int)keyboardShortcut.getKey().charValue()+"){\n");
                write("      document.location = '"+keyboardShortcut.getValue()+"';\n");
                write("    }\n");
            }
            write("  }\n");
            write("});\n");
           
            write("enableInfoKeybordShortcut('\\\\?');\n");
            for (Map.Entry<Character, String> keyboardShortcut : keyboardShortcuts.entrySet()) {
                write("enableInfoKeybordShortcut('"+ keyboardShortcut.getKey() + "');\n");
            }
           
            close("script");
        }
    }

    protected void registerAdditionalKeyboardShortcuts() throws IOException {
        // for subclasses
    }

    protected final void registerKeyboardShortcut(char c, String url) throws IOException {
        keyboardShortcuts.put(c, url);
    }

    protected final void writeLinkSourceCode(Object obj) throws IOException {
        String srcUrl = linkRenderer().getSrcUrl(obj);
        if (tool.isIncludeSourceCode() && srcUrl != null) {
            open("a class='link-source-code' href='" + srcUrl + "'");
            write("<i class='icon-source-code'></i>");
            write("Source Code");
            close("a");
        }
    }
   
    protected final void writeBy(Object obj) throws IOException {
        List<Annotation> annotations;
       
        if( obj instanceof Declaration ) {
            annotations = ((Declaration) obj).getAnnotations();
        } else if ( obj instanceof Module ) {
            annotations = ((Module) obj).getAnnotations();
        } else if( obj instanceof Package ) {
            annotations = ((Package) obj).getAnnotations();
        } else {
            throw new IllegalArgumentException();
        }
       
        List<String> authors = new ArrayList<>();
        for (Annotation annotation : annotations) {
            if (annotation.getName().equals("by")) {
                for (String author : annotation.getPositionalArguments()) {
                    authors.add(author);
                }
            }
        }
       
        if (!authors.isEmpty()) {
            open("div class='by section'");
            around("span class='title'", "By: ");
            around("span class='value'", Util.join(", ", authors));
            close("div");
        }       
    }
   
    protected final void writeIcon(Object obj) throws IOException {
        List<String> icons = getIcons(obj);
   
        int i = 0;
        for (String icon : icons) {
            open("i class='" + icon + "'");
            i++;
        }
        while (i-- > 0) {
            close("i");
        }
    }

    protected final List<String> getIcons(Object obj) {
        List<String> icons = new ArrayList<String>();

        if( obj instanceof Declaration ) {
            Declaration decl = (Declaration) obj;

            Annotation deprecated = Util.findAnnotation(decl, "deprecated");
            if (deprecated != null) {
                icons.add("icon-decoration-deprecated");
            }

            if( decl instanceof ClassOrInterface ) {
                if (decl instanceof Interface) {
                    icons.add("icon-interface");
                    if (Util.isEnumerated((ClassOrInterface) decl)) {
                        icons.add("icon-decoration-enumerated");
                    }
                }
                if (decl instanceof Class) {
                    Class klass = (Class) decl;
                    if (klass.isAnonymous()) {
                        icons.add("icon-object");
                    } else {
                        icons.add("icon-class");
                    }
                    if (klass.isAbstract()) {
                        icons.add("icon-decoration-abstract");
                    }
                    if (klass.isFinal() && !klass.isAnonymous() && !klass.isAnnotation()) {
                        icons.add("icon-decoration-final");
                    }
                    if (Util.isEnumerated(klass)) {
                        icons.add("icon-decoration-enumerated");
                    }
                }
                if (!decl.isShared() ) {
                    icons.add("icon-decoration-local");
                }
            }

            if (decl instanceof TypedDeclaration) {
                if( decl.isShared() ) {
                    icons.add("icon-shared-member");
                }
                else {
                    icons.add("icon-local-member");
                }
                if( decl.isFormal() ) {
                    icons.add("icon-decoration-formal");
                }
                if (decl.isActual()) {
                    Declaration refinedDeclaration = decl.getRefinedDeclaration();
                    if (refinedDeclaration != null) {
                        if (refinedDeclaration.isFormal()) {
                            icons.add("icon-decoration-impl");
                        }
                        if (refinedDeclaration.isDefault()) {
                            icons.add("icon-decoration-over");
                        }
                    }
                }
                if( ((TypedDeclaration) decl).isVariable() ) {
                    icons.add("icon-decoration-variable");
                }
            }
           
            if (decl instanceof TypeAlias || decl instanceof NothingType) {
                icons.add("icon-type-alias");
            }
           
            if (decl.isAnnotation()) {
                icons.add("icon-decoration-annotation");
            }
        }

        if (obj instanceof Package) {
            Package pkg = (Package) obj;

            icons.add("icon-package");
            if (!pkg.isShared()) {
                icons.add("icon-decoration-local");
            }
        }
       
        if (obj instanceof ModuleImport) {
            ModuleImport moduleImport = (ModuleImport) obj;

            icons.add("icon-module");
            if (moduleImport.isExport()) {
                icons.add("icon-module-exported-decoration");
            }
            if (moduleImport.isOptional()) {
                icons.add("icon-module-optional-decoration");
            }
        }

        return icons;
    }
   
    protected final void writePackageNavigation(Package pkg) throws IOException {
        open("span class='package-identifier'");
        if (!module.isDefault()) {
            List<String> moduleNames = module.getName();
            List<String> pkgNames = pkg.getName();
            List<String> subpkgNames = pkgNames.subList(moduleNames.size(), pkgNames.size());
            linkRenderer().to(module.getRootPackage()).write();
            if (!subpkgNames.isEmpty()) {
                StringBuilder subpkgNameBuilder = new StringBuilder(module.getNameAsString());
                for (String subpkgName : subpkgNames) {
                    subpkgNameBuilder.append(".").append(subpkgName);
                    Package subpkg = module.getDirectPackage(subpkgNameBuilder.toString());
                    write(".");
                    if (subpkg != null) {
                        linkRenderer().to(subpkg).useCustomText(subpkgName).write();
                    } else {
                        write(subpkgName);
                    }
                }
            }
        } else {
            linkRenderer().to(pkg).write();
        }
        close("span");
    }
   
    protected final void writePackagesTable(String title, List<Package> packages) throws IOException {
        if (!packages.isEmpty()) {
            openTable("section-packages", title, 2, true);
            for (Package pkg : packages) {
                writePackagesTableRow(pkg);
            }
            closeTable();
        }
    }

    protected final void writePackagesTableRow(Package pkg) throws IOException {
        open("tr");

        open("td");
        writeIcon(pkg);
        if (pkg.getNameAsString().isEmpty()) {
            around("a class='link' href='index.html'", "default package");
        } else {
            around("a class='link' href='" + tool.getObjectUrl(getFromObject(), pkg) + "'", pkg.getNameAsString());
        }
        close("td");

        open("td");
        write(Util.getDocFirstLine(pkg, linkRenderer()));
        close("td");

        close("tr");
    }
   
    protected final void writeAnnotations(Referenceable referenceable) throws IOException {
        Tree.AnnotationList annotationList = null;

        Node node = tool.getNode(referenceable);
        if (node instanceof Tree.Declaration) {
            annotationList = ((Tree.Declaration) node).getAnnotationList();
        } else if (node instanceof Tree.ImportModule) {
            annotationList = ((Tree.ImportModule) node).getAnnotationList();
        } else if (node instanceof Tree.ModuleDescriptor) {
            annotationList = ((Tree.ModuleDescriptor) node).getAnnotationList();
        } else if (node instanceof Tree.PackageDescriptor) {
            annotationList = ((Tree.PackageDescriptor) node).getAnnotationList();
        }

        if (annotationList != null) {
            annotationList.visit(new WriteAnnotationsVisitor());
        }
    }

    private class WriteAnnotationsVisitor extends Visitor {
   
        private Tree.Annotation annotation;
        private Tree.InvocationExpression invocationExpression;
        private Tree.PositionalArgument positionalArgument;
   
        @Override
        public void visit(Tree.AnnotationList that) {
            try {
                boolean containsAnnotations = false;
                for (Tree.Annotation annotation : that.getAnnotations()) {
                    if (!isCeylonLanguageAnnotation(annotation)) {
                        containsAnnotations = true;
                        break;
                    }
                }
               
                if( containsAnnotations ) {
                    open("div class='annotations section'");
                    around("span class='title'", "Annotations: ");
                    open("ul");
                    super.visit(that);
                    close("ul");
                    close("div");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
       
        @Override
        public void visit(Tree.AnonymousAnnotation that) {
            // noop
        }
   
        @Override
        public void visit(Tree.Annotation that) {
            try {
                if (isCeylonLanguageAnnotation(that)) {
                    return;
                }
                open("li");
                Tree.Annotation old = annotation;
                annotation = that;
                super.visit(that);
                annotation = old;
                close("li");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.MemberOrTypeExpression that) {
            try {
                linkRenderer().to(that.getDeclaration()).write();
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.InvocationExpression that) {
            Tree.InvocationExpression old = invocationExpression;
            invocationExpression = that;
            super.visit(that);
            invocationExpression = old;
        }
   
        @Override
        public void visit(Tree.PositionalArgumentList that) {
            try {
                if (!that.getPositionalArguments().isEmpty() || annotation != invocationExpression) {
                    write("(");
                }
                positionalArgument = null;
                super.visit(that);
                positionalArgument = null;
                if (!that.getPositionalArguments().isEmpty() || annotation != invocationExpression) {
                    write(")");
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
       
        @Override
        public void visit(Tree.PositionalArgument that) {
            try {
                if (positionalArgument != null) {
                    write(", ");
                }
                super.visit(that);
                positionalArgument = that;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.NamedArgumentList that) {
            try {
                write("{");
                super.visit(that);
                write("}");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
       
        @Override
        public void visit(Tree.NamedArgument that) {
            try {
                write(that.getParameter().getName());
                write("=");
                super.visit(that);
                write(";");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
       
        @Override
        public void visit(Tree.SequenceEnumeration that) {
            try {
                Tree.PositionalArgument old = positionalArgument;
                positionalArgument = null;
                write("{");
                super.visit(that);
                write("}");
                positionalArgument = old;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.Tuple that) {
            try {
                Tree.PositionalArgument old = positionalArgument;
                positionalArgument = null;
                write("[");
                super.visit(that);
                write("]");
                positionalArgument = old;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.Literal that) {
            try {
                open("span class='literal'");
                if (that instanceof Tree.StringLiteral) {
                    write("&quot;");
                }
                write(that.getText());
                if (that instanceof Tree.StringLiteral) {
                    write("&quot;");
                }
                close("span");
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.MemberLiteral that) {
            try {
                if (that instanceof Tree.ValueLiteral) {
                    write("`");
                    around("span class='keyword'", "value ");
                } else if (that instanceof Tree.FunctionLiteral) {
                    write("`");
                    around("span class='keyword'", "function ");
                }
                linkRenderer().to(that.getDeclaration()).write();
                write("`");
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.TypeLiteral that) {
            try {
                if (that instanceof Tree.AliasLiteral) {
                    write("`");
                    around("span class='keyword'", "alias ");
                } else if (that instanceof Tree.ClassLiteral) {
                    write("`");
                    around("span class='keyword'", "class ");
                } else if (that instanceof Tree.InterfaceLiteral) {
                    write("`");
                    around("span class='keyword'", "interface ");
                } else if (that instanceof Tree.TypeParameterLiteral) {
                    write("`");
                    around("span class='keyword'", "given ");
                }
                linkRenderer().to(that.getDeclaration()).write();
                write("`");
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.ModuleLiteral that) {
            try {
                write("`");
                around("span class='keyword'", "module ");
                linkRenderer().to(that.getImportPath().getModel()).write();
                write("`");
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
   
        @Override
        public void visit(Tree.PackageLiteral that) {
            try {
                write("`");
                around("span class='keyword'", "package");
                write(" ");
                linkRenderer().to(that.getImportPath().getModel()).write();
                write("`");
                super.visit(that);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        private boolean isCeylonLanguageAnnotation(Tree.Annotation annotation) {
            if (annotation.getPrimary() instanceof Tree.MemberOrTypeExpression) {
                Declaration declaration = ((Tree.MemberOrTypeExpression) annotation.getPrimary()).getDeclaration();
                if (declaration.getQualifiedNameString().startsWith(AbstractModelLoader.CEYLON_LANGUAGE)) {
                    return true;
                }
            }
            return false;
        }
   
    }   

    protected abstract Object getFromObject();   
   
}
TOP

Related Classes of com.redhat.ceylon.ceylondoc.CeylonDoc$WriteAnnotationsVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.