Mon, 03 Jun 2013 17:09:26 -0700
8006615: [doclint] move remaining messages into resource bundle
Reviewed-by: mcimadamore, vromero
1 /*
2 * Copyright (c) 2010, 2013, 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 */
26 package com.sun.tools.doclint;
28 import java.util.Set;
29 import java.util.Collections;
30 import java.util.EnumMap;
31 import java.util.EnumSet;
32 import java.util.HashMap;
33 import java.util.Map;
35 import javax.lang.model.element.Name;
37 import static com.sun.tools.doclint.HtmlTag.Attr.*;
39 /**
40 * Enum representing HTML tags.
41 *
42 * The intent of this class is to embody the semantics of W3C HTML 4.01
43 * to the extent supported/used by javadoc.
44 *
45 * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
46 * Eventually, these two should be merged back together, and possibly made
47 * public.
48 *
49 * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
50 * @author Bhavesh Patel
51 * @author Jonathan Gibbons (revised)
52 */
53 public enum HtmlTag {
54 A(BlockType.INLINE, EndKind.REQUIRED,
55 attrs(AttrKind.OK, HREF, TARGET, NAME)),
57 B(BlockType.INLINE, EndKind.REQUIRED,
58 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
60 BIG(BlockType.INLINE, EndKind.REQUIRED,
61 EnumSet.of(Flag.EXPECT_CONTENT)),
63 BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
64 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
66 BODY(BlockType.OTHER, EndKind.REQUIRED),
68 BR(BlockType.INLINE, EndKind.NONE,
69 attrs(AttrKind.USE_CSS, CLEAR)),
71 CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
72 EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
74 CENTER(BlockType.BLOCK, EndKind.REQUIRED,
75 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
77 CITE(BlockType.INLINE, EndKind.REQUIRED,
78 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
80 CODE(BlockType.INLINE, EndKind.REQUIRED,
81 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
83 DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
84 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
86 DIV(BlockType.BLOCK, EndKind.REQUIRED,
87 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
89 DL(BlockType.BLOCK, EndKind.REQUIRED,
90 EnumSet.of(Flag.EXPECT_CONTENT),
91 attrs(AttrKind.USE_CSS, COMPACT)) {
92 @Override
93 public boolean accepts(HtmlTag t) {
94 return (t == DT) || (t == DD);
95 }
96 },
98 DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
99 EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
101 EM(BlockType.INLINE, EndKind.REQUIRED,
102 EnumSet.of(Flag.NO_NEST)),
104 FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
105 EnumSet.of(Flag.EXPECT_CONTENT),
106 attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
108 FRAME(BlockType.OTHER, EndKind.NONE),
110 FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
112 H1(BlockType.BLOCK, EndKind.REQUIRED),
113 H2(BlockType.BLOCK, EndKind.REQUIRED),
114 H3(BlockType.BLOCK, EndKind.REQUIRED),
115 H4(BlockType.BLOCK, EndKind.REQUIRED),
116 H5(BlockType.BLOCK, EndKind.REQUIRED),
117 H6(BlockType.BLOCK, EndKind.REQUIRED),
119 HEAD(BlockType.OTHER, EndKind.REQUIRED),
121 HR(BlockType.BLOCK, EndKind.NONE),
123 HTML(BlockType.OTHER, EndKind.REQUIRED),
125 I(BlockType.INLINE, EndKind.REQUIRED,
126 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
128 IMG(BlockType.INLINE, EndKind.NONE,
129 attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
130 attrs(AttrKind.OBSOLETE, NAME),
131 attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
133 LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
134 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
135 attrs(AttrKind.OK, VALUE)),
137 LINK(BlockType.OTHER, EndKind.NONE),
139 MENU(BlockType.BLOCK, EndKind.REQUIRED) {
140 @Override
141 public boolean accepts(HtmlTag t) {
142 return (t == LI);
143 }
144 },
146 META(BlockType.OTHER, EndKind.NONE),
148 NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
150 NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
152 OL(BlockType.BLOCK, EndKind.REQUIRED,
153 EnumSet.of(Flag.EXPECT_CONTENT),
154 attrs(AttrKind.USE_CSS, START, TYPE)){
155 @Override
156 public boolean accepts(HtmlTag t) {
157 return (t == LI);
158 }
159 },
161 P(BlockType.BLOCK, EndKind.OPTIONAL,
162 EnumSet.of(Flag.EXPECT_CONTENT),
163 attrs(AttrKind.USE_CSS, ALIGN)),
165 PRE(BlockType.BLOCK, EndKind.REQUIRED,
166 EnumSet.of(Flag.EXPECT_CONTENT)) {
167 @Override
168 public boolean accepts(HtmlTag t) {
169 switch (t) {
170 case IMG: case BIG: case SMALL: case SUB: case SUP:
171 return false;
172 default:
173 return (t.blockType == BlockType.INLINE);
174 }
175 }
176 },
178 SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
180 SMALL(BlockType.INLINE, EndKind.REQUIRED,
181 EnumSet.of(Flag.EXPECT_CONTENT)),
183 SPAN(BlockType.INLINE, EndKind.REQUIRED,
184 EnumSet.of(Flag.EXPECT_CONTENT)),
186 STRONG(BlockType.INLINE, EndKind.REQUIRED,
187 EnumSet.of(Flag.EXPECT_CONTENT)),
189 SUB(BlockType.INLINE, EndKind.REQUIRED,
190 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
192 SUP(BlockType.INLINE, EndKind.REQUIRED,
193 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
195 TABLE(BlockType.BLOCK, EndKind.REQUIRED,
196 EnumSet.of(Flag.EXPECT_CONTENT),
197 attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
198 CELLPADDING, CELLSPACING),
199 attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)) {
200 @Override
201 public boolean accepts(HtmlTag t) {
202 switch (t) {
203 case CAPTION:
204 case THEAD: case TBODY: case TFOOT:
205 case TR: // HTML 3.2
206 return true;
207 default:
208 return false;
209 }
210 }
211 },
213 TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
214 EnumSet.of(Flag.EXPECT_CONTENT),
215 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
216 @Override
217 public boolean accepts(HtmlTag t) {
218 return (t == TR);
219 }
220 },
222 TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
223 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
224 attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
225 ALIGN, CHAR, CHAROFF, VALIGN),
226 attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
228 TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
229 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
230 @Override
231 public boolean accepts(HtmlTag t) {
232 return (t == TR);
233 }
234 },
236 TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
237 EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
238 attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
239 ALIGN, CHAR, CHAROFF, VALIGN),
240 attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
242 THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
243 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
244 @Override
245 public boolean accepts(HtmlTag t) {
246 return (t == TR);
247 }
248 },
250 TITLE(BlockType.OTHER, EndKind.REQUIRED),
252 TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
253 attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
254 attrs(AttrKind.USE_CSS, BGCOLOR)) {
255 @Override
256 public boolean accepts(HtmlTag t) {
257 return (t == TH) || (t == TD);
258 }
259 },
261 TT(BlockType.INLINE, EndKind.REQUIRED,
262 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
264 U(BlockType.INLINE, EndKind.REQUIRED,
265 EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
267 UL(BlockType.BLOCK, EndKind.REQUIRED,
268 EnumSet.of(Flag.EXPECT_CONTENT),
269 attrs(AttrKind.USE_CSS, COMPACT, TYPE)){
270 @Override
271 public boolean accepts(HtmlTag t) {
272 return (t == LI);
273 }
274 },
276 VAR(BlockType.INLINE, EndKind.REQUIRED);
278 /**
279 * Enum representing the type of HTML element.
280 */
281 public static enum BlockType {
282 BLOCK,
283 INLINE,
284 LIST_ITEM,
285 TABLE_ITEM,
286 OTHER;
287 }
289 /**
290 * Enum representing HTML end tag requirement.
291 */
292 public static enum EndKind {
293 NONE,
294 OPTIONAL,
295 REQUIRED;
296 }
298 public static enum Flag {
299 ACCEPTS_BLOCK,
300 ACCEPTS_INLINE,
301 EXPECT_CONTENT,
302 NO_NEST
303 }
305 public static enum Attr {
306 ABBR,
307 ALIGN,
308 ALT,
309 AXIS,
310 BGCOLOR,
311 BORDER,
312 CELLSPACING,
313 CELLPADDING,
314 CHAR,
315 CHAROFF,
316 CLEAR,
317 CLASS,
318 COLOR,
319 COLSPAN,
320 COMPACT,
321 FACE,
322 FRAME,
323 HEADERS,
324 HEIGHT,
325 HREF,
326 HSPACE,
327 ID,
328 NAME,
329 NOWRAP,
330 REVERSED,
331 ROWSPAN,
332 RULES,
333 SCOPE,
334 SIZE,
335 SPACE,
336 SRC,
337 START,
338 STYLE,
339 SUMMARY,
340 TARGET,
341 TYPE,
342 VALIGN,
343 VALUE,
344 VSPACE,
345 WIDTH;
347 public String getText() {
348 return name().toLowerCase();
349 }
351 static final Map<String,Attr> index = new HashMap<String,Attr>();
352 static {
353 for (Attr t: values()) {
354 index.put(t.getText(), t);
355 }
356 }
357 }
359 public static enum AttrKind {
360 INVALID,
361 OBSOLETE,
362 USE_CSS,
363 OK
364 }
366 // This class exists to avoid warnings from using parameterized vararg type
367 // Map<Attr,AttrKind> in signature of HtmlTag constructor.
368 private static class AttrMap extends EnumMap<Attr,AttrKind> {
369 private static final long serialVersionUID = 0;
370 AttrMap() {
371 super(Attr.class);
372 }
373 }
376 public final BlockType blockType;
377 public final EndKind endKind;
378 public final Set<Flag> flags;
379 private final Map<Attr,AttrKind> attrs;
381 HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
382 this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
383 }
385 HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
386 this.blockType = blockType;
387 this.endKind = endKind;
388 this.flags = flags;
389 this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
390 for (Map<Attr,AttrKind> m: attrMaps)
391 this.attrs.putAll(m);
392 attrs.put(Attr.CLASS, AttrKind.OK);
393 attrs.put(Attr.ID, AttrKind.OK);
394 attrs.put(Attr.STYLE, AttrKind.OK);
395 }
397 public boolean accepts(HtmlTag t) {
398 if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
399 return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
400 } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
401 return (t.blockType == BlockType.BLOCK);
402 } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
403 return (t.blockType == BlockType.INLINE);
404 } else
405 switch (blockType) {
406 case BLOCK:
407 case INLINE:
408 return (t.blockType == BlockType.INLINE);
409 case OTHER:
410 // OTHER tags are invalid in doc comments, and will be
411 // reported separately, so silently accept/ignore any content
412 return true;
413 default:
414 // any combination which could otherwise arrive here
415 // ought to have been handled in an overriding method
416 throw new AssertionError(this + ":" + t);
417 }
418 }
420 public boolean acceptsText() {
421 // generally, anywhere we can put text we can also put inline tag
422 // so check if a typical inline tag is allowed
423 return accepts(B);
424 }
426 public String getText() {
427 return name().toLowerCase();
428 }
430 public Attr getAttr(Name attrName) {
431 return Attr.index.get(attrName.toString().toLowerCase());
432 }
434 public AttrKind getAttrKind(Name attrName) {
435 AttrKind k = attrs.get(getAttr(attrName)); // null-safe
436 return (k == null) ? AttrKind.INVALID : k;
437 }
439 private static AttrMap attrs(AttrKind k, Attr... attrs) {
440 AttrMap map = new AttrMap();
441 for (Attr a: attrs) map.put(a, k);
442 return map;
443 }
445 private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
446 static {
447 for (HtmlTag t: values()) {
448 index.put(t.getText(), t);
449 }
450 }
452 static HtmlTag get(Name tagName) {
453 return index.get(tagName.toString().toLowerCase());
454 }
455 }