src/share/classes/com/sun/tools/doclint/HtmlTag.java

Fri, 09 May 2014 20:33:21 -0700

author
mfang
date
Fri, 09 May 2014 20:33:21 -0700
changeset 2388
0add97444be9
parent 2051
96dcb66e6b0a
child 2413
fe033d997ddf
permissions
-rw-r--r--

8041424: 8u20 l10n resource file translation update 1
Reviewed-by: naoto, yhuang

     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.Locale;
    34 import java.util.Map;
    36 import javax.lang.model.element.Name;
    38 import static com.sun.tools.doclint.HtmlTag.Attr.*;
    40 /**
    41  * Enum representing HTML tags.
    42  *
    43  * The intent of this class is to embody the semantics of W3C HTML 4.01
    44  * to the extent supported/used by javadoc.
    45  * In time, we may wish to transition javadoc and doclint to using HTML 5.
    46  *
    47  * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
    48  * Eventually, these two should be merged back together, and possibly made
    49  * public.
    50  *
    51  * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
    52  * @see <a href="http://www.w3.org/TR/html5/">HTML 5 Specification</a>
    53  * @author Bhavesh Patel
    54  * @author Jonathan Gibbons (revised)
    55  */
    56 public enum HtmlTag {
    57     A(BlockType.INLINE, EndKind.REQUIRED,
    58             attrs(AttrKind.OK, HREF, TARGET, NAME)),
    60     B(BlockType.INLINE, EndKind.REQUIRED,
    61             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    63     BIG(BlockType.INLINE, EndKind.REQUIRED,
    64             EnumSet.of(Flag.EXPECT_CONTENT)),
    66     BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
    67             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    69     BODY(BlockType.OTHER, EndKind.REQUIRED),
    71     BR(BlockType.INLINE, EndKind.NONE,
    72             attrs(AttrKind.USE_CSS, CLEAR)),
    74     CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
    75             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    77     CENTER(BlockType.BLOCK, EndKind.REQUIRED,
    78             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    80     CITE(BlockType.INLINE, EndKind.REQUIRED,
    81             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    83     CODE(BlockType.INLINE, EndKind.REQUIRED,
    84             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    86     DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
    87             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    89     DFN(BlockType.INLINE, EndKind.REQUIRED,
    90             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    92     DIV(BlockType.BLOCK, EndKind.REQUIRED,
    93             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    95     DL(BlockType.BLOCK, EndKind.REQUIRED,
    96             EnumSet.of(Flag.EXPECT_CONTENT),
    97             attrs(AttrKind.USE_CSS, COMPACT)) {
    98         @Override
    99         public boolean accepts(HtmlTag t) {
   100             return (t == DT) || (t == DD);
   101         }
   102     },
   104     DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   105             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
   107     EM(BlockType.INLINE, EndKind.REQUIRED,
   108             EnumSet.of(Flag.NO_NEST)),
   110     FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
   111             EnumSet.of(Flag.EXPECT_CONTENT),
   112             attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
   114     FRAME(BlockType.OTHER, EndKind.NONE),
   116     FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
   118     H1(BlockType.BLOCK, EndKind.REQUIRED),
   119     H2(BlockType.BLOCK, EndKind.REQUIRED),
   120     H3(BlockType.BLOCK, EndKind.REQUIRED),
   121     H4(BlockType.BLOCK, EndKind.REQUIRED),
   122     H5(BlockType.BLOCK, EndKind.REQUIRED),
   123     H6(BlockType.BLOCK, EndKind.REQUIRED),
   125     HEAD(BlockType.OTHER, EndKind.REQUIRED),
   127     HR(BlockType.BLOCK, EndKind.NONE,
   128             attrs(AttrKind.OK, WIDTH)), // OK in 4.01; not allowed in 5
   130     HTML(BlockType.OTHER, EndKind.REQUIRED),
   132     I(BlockType.INLINE, EndKind.REQUIRED,
   133             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   135     IMG(BlockType.INLINE, EndKind.NONE,
   136             attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
   137             attrs(AttrKind.OBSOLETE, NAME),
   138             attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
   140     LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   141             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   142             attrs(AttrKind.OK, VALUE)),
   144     LINK(BlockType.OTHER, EndKind.NONE),
   146     MENU(BlockType.BLOCK, EndKind.REQUIRED) {
   147         @Override
   148         public boolean accepts(HtmlTag t) {
   149             return (t == LI);
   150         }
   151     },
   153     META(BlockType.OTHER, EndKind.NONE),
   155     NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
   157     NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
   159     OL(BlockType.BLOCK, EndKind.REQUIRED,
   160             EnumSet.of(Flag.EXPECT_CONTENT),
   161             attrs(AttrKind.OK, START, TYPE)) {
   162         @Override
   163         public boolean accepts(HtmlTag t) {
   164             return (t == LI);
   165         }
   166     },
   168     P(BlockType.BLOCK, EndKind.OPTIONAL,
   169             EnumSet.of(Flag.EXPECT_CONTENT),
   170             attrs(AttrKind.USE_CSS, ALIGN)),
   172     PRE(BlockType.BLOCK, EndKind.REQUIRED,
   173             EnumSet.of(Flag.EXPECT_CONTENT)) {
   174         @Override
   175         public boolean accepts(HtmlTag t) {
   176             switch (t) {
   177                 case IMG: case BIG: case SMALL: case SUB: case SUP:
   178                     return false;
   179                 default:
   180                     return (t.blockType == BlockType.INLINE);
   181             }
   182         }
   183     },
   185     SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
   187     SMALL(BlockType.INLINE, EndKind.REQUIRED,
   188             EnumSet.of(Flag.EXPECT_CONTENT)),
   190     SPAN(BlockType.INLINE, EndKind.REQUIRED,
   191             EnumSet.of(Flag.EXPECT_CONTENT)),
   193     STRONG(BlockType.INLINE, EndKind.REQUIRED,
   194             EnumSet.of(Flag.EXPECT_CONTENT)),
   196     SUB(BlockType.INLINE, EndKind.REQUIRED,
   197             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   199     SUP(BlockType.INLINE, EndKind.REQUIRED,
   200             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   202     TABLE(BlockType.BLOCK, EndKind.REQUIRED,
   203             EnumSet.of(Flag.EXPECT_CONTENT),
   204             attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
   205                 CELLPADDING, CELLSPACING, WIDTH), // width OK in 4.01; not allowed in 5
   206             attrs(AttrKind.USE_CSS, ALIGN, BGCOLOR)) {
   207         @Override
   208         public boolean accepts(HtmlTag t) {
   209             switch (t) {
   210                 case CAPTION:
   211                 case THEAD: case TBODY: case TFOOT:
   212                 case TR: // HTML 3.2
   213                     return true;
   214                 default:
   215                     return false;
   216             }
   217         }
   218     },
   220     TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   221             EnumSet.of(Flag.EXPECT_CONTENT),
   222             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   223         @Override
   224         public boolean accepts(HtmlTag t) {
   225             return (t == TR);
   226         }
   227     },
   229     TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   230             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   231             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   232                 ALIGN, CHAR, CHAROFF, VALIGN),
   233             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   235     TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   236             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   237         @Override
   238         public boolean accepts(HtmlTag t) {
   239             return (t == TR);
   240         }
   241     },
   243     TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   244             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   245             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   246                 ALIGN, CHAR, CHAROFF, VALIGN),
   247             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   249     THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   250             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   251         @Override
   252         public boolean accepts(HtmlTag t) {
   253             return (t == TR);
   254         }
   255     },
   257     TITLE(BlockType.OTHER, EndKind.REQUIRED),
   259     TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   260             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
   261             attrs(AttrKind.USE_CSS, BGCOLOR)) {
   262         @Override
   263         public boolean accepts(HtmlTag t) {
   264             return (t == TH) || (t == TD);
   265         }
   266     },
   268     TT(BlockType.INLINE, EndKind.REQUIRED,
   269             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   271     U(BlockType.INLINE, EndKind.REQUIRED,
   272             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   274     UL(BlockType.BLOCK, EndKind.REQUIRED,
   275             EnumSet.of(Flag.EXPECT_CONTENT),
   276             attrs(AttrKind.OK, COMPACT, TYPE)) { // OK in 4.01; not allowed in 5
   277         @Override
   278         public boolean accepts(HtmlTag t) {
   279             return (t == LI);
   280         }
   281     },
   283     VAR(BlockType.INLINE, EndKind.REQUIRED);
   285     /**
   286      * Enum representing the type of HTML element.
   287      */
   288     public static enum BlockType {
   289         BLOCK,
   290         INLINE,
   291         LIST_ITEM,
   292         TABLE_ITEM,
   293         OTHER;
   294     }
   296     /**
   297      * Enum representing HTML end tag requirement.
   298      */
   299     public static enum EndKind {
   300         NONE,
   301         OPTIONAL,
   302         REQUIRED;
   303     }
   305     public static enum Flag {
   306         ACCEPTS_BLOCK,
   307         ACCEPTS_INLINE,
   308         EXPECT_CONTENT,
   309         NO_NEST
   310     }
   312     public static enum Attr {
   313         ABBR,
   314         ALIGN,
   315         ALT,
   316         AXIS,
   317         BGCOLOR,
   318         BORDER,
   319         CELLSPACING,
   320         CELLPADDING,
   321         CHAR,
   322         CHAROFF,
   323         CLEAR,
   324         CLASS,
   325         COLOR,
   326         COLSPAN,
   327         COMPACT,
   328         FACE,
   329         FRAME,
   330         HEADERS,
   331         HEIGHT,
   332         HREF,
   333         HSPACE,
   334         ID,
   335         NAME,
   336         NOWRAP,
   337         REVERSED,
   338         ROWSPAN,
   339         RULES,
   340         SCOPE,
   341         SIZE,
   342         SPACE,
   343         SRC,
   344         START,
   345         STYLE,
   346         SUMMARY,
   347         TARGET,
   348         TYPE,
   349         VALIGN,
   350         VALUE,
   351         VSPACE,
   352         WIDTH;
   354         public String getText() {
   355             return toLowerCase(name());
   356         }
   358         static final Map<String,Attr> index = new HashMap<String,Attr>();
   359         static {
   360             for (Attr t: values()) {
   361                 index.put(t.getText(), t);
   362             }
   363         }
   364     }
   366     public static enum AttrKind {
   367         INVALID,
   368         OBSOLETE,
   369         USE_CSS,
   370         OK
   371     }
   373     // This class exists to avoid warnings from using parameterized vararg type
   374     // Map<Attr,AttrKind> in signature of HtmlTag constructor.
   375     private static class AttrMap extends EnumMap<Attr,AttrKind>  {
   376         private static final long serialVersionUID = 0;
   377         AttrMap() {
   378             super(Attr.class);
   379         }
   380     }
   383     public final BlockType blockType;
   384     public final EndKind endKind;
   385     public final Set<Flag> flags;
   386     private final Map<Attr,AttrKind> attrs;
   388     HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
   389         this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
   390     }
   392     HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
   393         this.blockType = blockType;
   394         this.endKind = endKind;
   395         this.flags = flags;
   396         this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
   397         for (Map<Attr,AttrKind> m: attrMaps)
   398             this.attrs.putAll(m);
   399         attrs.put(Attr.CLASS, AttrKind.OK);
   400         attrs.put(Attr.ID, AttrKind.OK);
   401         attrs.put(Attr.STYLE, AttrKind.OK);
   402     }
   404     public boolean accepts(HtmlTag t) {
   405         if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
   406             return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
   407         } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
   408             return (t.blockType == BlockType.BLOCK);
   409         } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
   410             return (t.blockType == BlockType.INLINE);
   411         } else
   412             switch (blockType) {
   413                 case BLOCK:
   414                 case INLINE:
   415                     return (t.blockType == BlockType.INLINE);
   416                 case OTHER:
   417                     // OTHER tags are invalid in doc comments, and will be
   418                     // reported separately, so silently accept/ignore any content
   419                     return true;
   420                 default:
   421                     // any combination which could otherwise arrive here
   422                     // ought to have been handled in an overriding method
   423                     throw new AssertionError(this + ":" + t);
   424             }
   425     }
   427     public boolean acceptsText() {
   428         // generally, anywhere we can put text we can also put inline tag
   429         // so check if a typical inline tag is allowed
   430         return accepts(B);
   431     }
   433     public String getText() {
   434         return toLowerCase(name());
   435     }
   437     public Attr getAttr(Name attrName) {
   438         return Attr.index.get(toLowerCase(attrName.toString()));
   439     }
   441     public AttrKind getAttrKind(Name attrName) {
   442         AttrKind k = attrs.get(getAttr(attrName)); // null-safe
   443         return (k == null) ? AttrKind.INVALID : k;
   444     }
   446     private static AttrMap attrs(AttrKind k, Attr... attrs) {
   447         AttrMap map = new AttrMap();
   448         for (Attr a: attrs) map.put(a, k);
   449         return map;
   450     }
   452     private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
   453     static {
   454         for (HtmlTag t: values()) {
   455             index.put(t.getText(), t);
   456         }
   457     }
   459     static HtmlTag get(Name tagName) {
   460         return index.get(toLowerCase(tagName.toString()));
   461     }
   463     private static String toLowerCase(String s) {
   464         return s.toLowerCase(Locale.US);
   465     }
   466 }

mercurial