1 /* 2 * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.javadoc.internal.doclets.toolkit.taglets; 27 28 import java.util.EnumSet; 29 import java.util.List; 30 import java.util.Set; 31 32 import javax.lang.model.element.Element; 33 34 import com.sun.source.doctree.DocTree; 35 import jdk.javadoc.doclet.Taglet.Location; 36 37 import jdk.javadoc.internal.doclets.toolkit.Content; 38 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper; 39 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder; 40 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 41 42 /** 43 * A simple single argument custom tag. 44 * 45 * <p><b>This is NOT part of any supported API. 46 * If you write code that depends on this, you do so at your own risk. 47 * This code and its internal interfaces are subject to change or 48 * deletion without notice.</b> 49 */ 50 51 public class SimpleTaglet extends BaseTaglet implements InheritableTaglet { 52 53 /** 54 * The header to output. 55 */ 56 protected String header; 57 58 /** 59 * Whether or not the taglet should generate output. 60 * Standard tags like at-author, at-since, at-version can be disabled 61 * by command-line options; custom tags created with -tag can be 62 * disabled with an X in the defining string. 63 */ 64 protected final boolean enabled; 65 66 /** 67 * Constructs a {@code SimpleTaglet}. 68 * 69 * @param tagName the name of this tag 70 * @param header the header to output 71 * @param locations the possible locations that this tag can appear in 72 * The string can contain 'p' for package, 't' for type, 73 * 'm' for method, 'c' for constructor and 'f' for field. 74 * See {@linbk #getLocations(String) getLocations} for the 75 * complete list. 76 */ SimpleTaglet(String tagName, String header, String locations)77 public SimpleTaglet(String tagName, String header, String locations) { 78 this(tagName, header, getLocations(locations), isEnabled(locations)); 79 } 80 81 /** 82 * Constructs a {@code SimpleTaglet}. 83 * 84 * @param tagKind the kind of this tag 85 * @param header the header to output 86 * @param locations the possible locations that this tag can appear in. 87 */ SimpleTaglet(DocTree.Kind tagKind, String header, Set<Location> locations)88 public SimpleTaglet(DocTree.Kind tagKind, String header, Set<Location> locations) { 89 this(tagKind, header, locations, true); 90 } 91 92 93 /** 94 * Constructs a {@code SimpleTaglet}. 95 * 96 * @param tagName the name of this tag 97 * @param header the header to output. 98 * @param locations the possible locations that this tag can appear in 99 */ SimpleTaglet(String tagName, String header, Set<Location> locations)100 public SimpleTaglet(String tagName, String header, Set<Location> locations) { 101 this(tagName, header, locations, true); 102 } 103 104 /** 105 * Constructs a {@code SimpleTaglet}. 106 * 107 * @param tagName the name of this tag 108 * @param header the header to output. 109 * @param locations the possible locations that this tag can appear in 110 */ SimpleTaglet(String tagName, String header, Set<Location> locations, boolean enabled)111 public SimpleTaglet(String tagName, String header, Set<Location> locations, boolean enabled) { 112 super(tagName, false, locations); 113 this.header = header; 114 this.enabled = enabled; 115 } 116 117 /** 118 * Constructs a {@code SimpleTaglet}. 119 * 120 * @param tagKind the kind of this tag 121 * @param header the header to output. 122 * @param locations the possible locations that this tag can appear in 123 */ SimpleTaglet(DocTree.Kind tagKind, String header, Set<Location> locations, boolean enabled)124 public SimpleTaglet(DocTree.Kind tagKind, String header, Set<Location> locations, boolean enabled) { 125 super(tagKind, false, locations); 126 this.header = header; 127 this.enabled = enabled; 128 } 129 getLocations(String locations)130 private static Set<Location> getLocations(String locations) { 131 Set<Location> set = EnumSet.noneOf(Location.class); 132 for (int i = 0; i < locations.length(); i++) { 133 switch (locations.charAt(i)) { 134 case 'a': case 'A': 135 return EnumSet.allOf(Location.class); 136 case 'c': case 'C': 137 set.add(Location.CONSTRUCTOR); 138 break; 139 case 'f': case 'F': 140 set.add(Location.FIELD); 141 break; 142 case 'm': case 'M': 143 set.add(Location.METHOD); 144 break; 145 case 'o': case 'O': 146 set.add(Location.OVERVIEW); 147 break; 148 case 'p': case 'P': 149 set.add(Location.PACKAGE); 150 break; 151 case 's': case 'S': // super-packages, anyone? 152 set.add(Location.MODULE); 153 break; 154 case 't': case 'T': 155 set.add(Location.TYPE); 156 break; 157 case 'x': case 'X': 158 break; 159 } 160 } 161 return set; 162 } 163 isEnabled(String locations)164 private static boolean isEnabled(String locations) { 165 return locations.matches("[^Xx]*"); 166 } 167 168 @Override inherit(DocFinder.Input input, DocFinder.Output output)169 public void inherit(DocFinder.Input input, DocFinder.Output output) { 170 List<? extends DocTree> tags = input.utils.getBlockTags(input.element, this); 171 if (!tags.isEmpty()) { 172 output.holder = input.element; 173 output.holderTag = tags.get(0); 174 CommentHelper ch = input.utils.getCommentHelper(output.holder); 175 output.inlineTags = input.isFirstSentence 176 ? ch.getFirstSentenceTrees(output.holderTag) 177 : ch.getTags(output.holderTag); 178 } 179 } 180 181 @Override getTagletOutput(Element element, DocTree tag, TagletWriter writer)182 public Content getTagletOutput(Element element, DocTree tag, TagletWriter writer) { 183 return header == null || tag == null ? null : writer.simpleTagOutput(element, tag, header); 184 } 185 186 @Override getTagletOutput(Element holder, TagletWriter writer)187 public Content getTagletOutput(Element holder, TagletWriter writer) { 188 Utils utils = writer.configuration().utils; 189 List<? extends DocTree> tags = utils.getBlockTags(holder, this); 190 if (header == null || tags.isEmpty()) { 191 return null; 192 } 193 return writer.simpleTagOutput(holder, tags, header); 194 } 195 } 196