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

Thu, 24 May 2018 18:02:46 +0800

author
aoqi
date
Thu, 24 May 2018 18:02:46 +0800
changeset 3446
e468915bad3a
parent 3315
6f0746b6de9f
parent 2525
2eb010b6cb22
permissions
-rw-r--r--

Merge

     1 /*
     2  * Copyright (c) 2010, 2016, 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.*;
    39 import com.sun.tools.javac.util.StringUtils;
    41 /**
    42  * Enum representing HTML tags.
    43  *
    44  * The intent of this class is to embody the semantics of W3C HTML 4.01
    45  * to the extent supported/used by javadoc.
    46  * In time, we may wish to transition javadoc and doclint to using HTML 5.
    47  *
    48  * This is derivative of com.sun.tools.doclets.formats.html.markup.HtmlTag.
    49  * Eventually, these two should be merged back together, and possibly made
    50  * public.
    51  *
    52  * @see <a href="http://www.w3.org/TR/REC-html40/">HTML 4.01 Specification</a>
    53  * @see <a href="http://www.w3.org/TR/html5/">HTML 5 Specification</a>
    54  * @author Bhavesh Patel
    55  * @author Jonathan Gibbons (revised)
    56  */
    57 public enum HtmlTag {
    58     A(BlockType.INLINE, EndKind.REQUIRED,
    59             attrs(AttrKind.OK, HREF, TARGET, NAME)),
    61     B(BlockType.INLINE, EndKind.REQUIRED,
    62             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    64     BIG(BlockType.INLINE, EndKind.REQUIRED,
    65             EnumSet.of(Flag.EXPECT_CONTENT)),
    67     BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
    68             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    70     BODY(BlockType.OTHER, EndKind.REQUIRED),
    72     BR(BlockType.INLINE, EndKind.NONE,
    73             attrs(AttrKind.USE_CSS, CLEAR)),
    75     CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
    76             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    78     CENTER(BlockType.BLOCK, EndKind.REQUIRED,
    79             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    81     CITE(BlockType.INLINE, EndKind.REQUIRED,
    82             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    84     CODE(BlockType.INLINE, EndKind.REQUIRED,
    85             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    87     DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
    88             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
    90     DFN(BlockType.INLINE, EndKind.REQUIRED,
    91             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
    93     DIV(BlockType.BLOCK, EndKind.REQUIRED,
    94             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
    96     DL(BlockType.BLOCK, EndKind.REQUIRED,
    97             EnumSet.of(Flag.EXPECT_CONTENT),
    98             attrs(AttrKind.USE_CSS, COMPACT)) {
    99         @Override
   100         public boolean accepts(HtmlTag t) {
   101             return (t == DT) || (t == DD);
   102         }
   103     },
   105     DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   106             EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
   108     EM(BlockType.INLINE, EndKind.REQUIRED,
   109             EnumSet.of(Flag.NO_NEST)),
   111     FONT(BlockType.INLINE, EndKind.REQUIRED, // tag itself is deprecated
   112             EnumSet.of(Flag.EXPECT_CONTENT),
   113             attrs(AttrKind.USE_CSS, SIZE, COLOR, FACE)),
   115     FRAME(BlockType.OTHER, EndKind.NONE),
   117     FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
   119     H1(BlockType.BLOCK, EndKind.REQUIRED),
   120     H2(BlockType.BLOCK, EndKind.REQUIRED),
   121     H3(BlockType.BLOCK, EndKind.REQUIRED),
   122     H4(BlockType.BLOCK, EndKind.REQUIRED),
   123     H5(BlockType.BLOCK, EndKind.REQUIRED),
   124     H6(BlockType.BLOCK, EndKind.REQUIRED),
   126     HEAD(BlockType.OTHER, EndKind.REQUIRED),
   128     HR(BlockType.BLOCK, EndKind.NONE,
   129             attrs(AttrKind.OK, WIDTH)), // OK in 4.01; not allowed in 5
   131     HTML(BlockType.OTHER, EndKind.REQUIRED),
   133     I(BlockType.INLINE, EndKind.REQUIRED,
   134             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   136     IMG(BlockType.INLINE, EndKind.NONE,
   137             attrs(AttrKind.OK, SRC, ALT, HEIGHT, WIDTH),
   138             attrs(AttrKind.OBSOLETE, NAME),
   139             attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
   141     LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
   142             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   143             attrs(AttrKind.OK, VALUE)),
   145     LINK(BlockType.OTHER, EndKind.NONE),
   147     MENU(BlockType.BLOCK, EndKind.REQUIRED) {
   148         @Override
   149         public boolean accepts(HtmlTag t) {
   150             return (t == LI);
   151         }
   152     },
   154     META(BlockType.OTHER, EndKind.NONE),
   156     NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
   158     NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
   160     OL(BlockType.BLOCK, EndKind.REQUIRED,
   161             EnumSet.of(Flag.EXPECT_CONTENT),
   162             attrs(AttrKind.OK, START, TYPE)) {
   163         @Override
   164         public boolean accepts(HtmlTag t) {
   165             return (t == LI);
   166         }
   167     },
   169     P(BlockType.BLOCK, EndKind.OPTIONAL,
   170             EnumSet.of(Flag.EXPECT_CONTENT),
   171             attrs(AttrKind.USE_CSS, ALIGN)),
   173     PRE(BlockType.BLOCK, EndKind.REQUIRED,
   174             EnumSet.of(Flag.EXPECT_CONTENT)) {
   175         @Override
   176         public boolean accepts(HtmlTag t) {
   177             switch (t) {
   178                 case IMG: case BIG: case SMALL: case SUB: case SUP:
   179                     return false;
   180                 default:
   181                     return (t.blockType == BlockType.INLINE);
   182             }
   183         }
   184     },
   186     SCRIPT(BlockType.OTHER, EndKind.REQUIRED,
   187             attrs(AttrKind.OK, SRC)),
   189     SMALL(BlockType.INLINE, EndKind.REQUIRED,
   190             EnumSet.of(Flag.EXPECT_CONTENT)),
   192     SPAN(BlockType.INLINE, EndKind.REQUIRED,
   193             EnumSet.of(Flag.EXPECT_CONTENT)),
   195     STRONG(BlockType.INLINE, EndKind.REQUIRED,
   196             EnumSet.of(Flag.EXPECT_CONTENT)),
   198     SUB(BlockType.INLINE, EndKind.REQUIRED,
   199             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   201     SUP(BlockType.INLINE, EndKind.REQUIRED,
   202             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   204     TABLE(BlockType.BLOCK, EndKind.REQUIRED,
   205             EnumSet.of(Flag.EXPECT_CONTENT),
   206             attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
   207                 CELLPADDING, CELLSPACING, WIDTH), // width OK in 4.01; not allowed in 5
   208             attrs(AttrKind.USE_CSS, ALIGN, BGCOLOR)) {
   209         @Override
   210         public boolean accepts(HtmlTag t) {
   211             switch (t) {
   212                 case CAPTION:
   213                 case THEAD: case TBODY: case TFOOT:
   214                 case TR: // HTML 3.2
   215                     return true;
   216                 default:
   217                     return false;
   218             }
   219         }
   220     },
   222     TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   223             EnumSet.of(Flag.EXPECT_CONTENT),
   224             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   225         @Override
   226         public boolean accepts(HtmlTag t) {
   227             return (t == TR);
   228         }
   229     },
   231     TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   232             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   233             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   234                 ALIGN, CHAR, CHAROFF, VALIGN),
   235             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   237     TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   238             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   239         @Override
   240         public boolean accepts(HtmlTag t) {
   241             return (t == TR);
   242         }
   243     },
   245     TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   246             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   247             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   248                 ALIGN, CHAR, CHAROFF, VALIGN),
   249             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   251     THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   252             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   253         @Override
   254         public boolean accepts(HtmlTag t) {
   255             return (t == TR);
   256         }
   257     },
   259     TITLE(BlockType.OTHER, EndKind.REQUIRED),
   261     TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   262             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
   263             attrs(AttrKind.USE_CSS, BGCOLOR)) {
   264         @Override
   265         public boolean accepts(HtmlTag t) {
   266             return (t == TH) || (t == TD);
   267         }
   268     },
   270     TT(BlockType.INLINE, EndKind.REQUIRED,
   271             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   273     U(BlockType.INLINE, EndKind.REQUIRED,
   274             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   276     UL(BlockType.BLOCK, EndKind.REQUIRED,
   277             EnumSet.of(Flag.EXPECT_CONTENT),
   278             attrs(AttrKind.OK, COMPACT, TYPE)) { // OK in 4.01; not allowed in 5
   279         @Override
   280         public boolean accepts(HtmlTag t) {
   281             return (t == LI);
   282         }
   283     },
   285     VAR(BlockType.INLINE, EndKind.REQUIRED);
   287     /**
   288      * Enum representing the type of HTML element.
   289      */
   290     public static enum BlockType {
   291         BLOCK,
   292         INLINE,
   293         LIST_ITEM,
   294         TABLE_ITEM,
   295         OTHER;
   296     }
   298     /**
   299      * Enum representing HTML end tag requirement.
   300      */
   301     public static enum EndKind {
   302         NONE,
   303         OPTIONAL,
   304         REQUIRED;
   305     }
   307     public static enum Flag {
   308         ACCEPTS_BLOCK,
   309         ACCEPTS_INLINE,
   310         EXPECT_CONTENT,
   311         NO_NEST
   312     }
   314     public static enum Attr {
   315         ABBR,
   316         ALIGN,
   317         ALT,
   318         AXIS,
   319         BGCOLOR,
   320         BORDER,
   321         CELLSPACING,
   322         CELLPADDING,
   323         CHAR,
   324         CHAROFF,
   325         CLEAR,
   326         CLASS,
   327         COLOR,
   328         COLSPAN,
   329         COMPACT,
   330         FACE,
   331         FRAME,
   332         HEADERS,
   333         HEIGHT,
   334         HREF,
   335         HSPACE,
   336         ID,
   337         NAME,
   338         NOWRAP,
   339         REVERSED,
   340         ROWSPAN,
   341         RULES,
   342         SCOPE,
   343         SIZE,
   344         SPACE,
   345         SRC,
   346         START,
   347         STYLE,
   348         SUMMARY,
   349         TARGET,
   350         TYPE,
   351         VALIGN,
   352         VALUE,
   353         VSPACE,
   354         WIDTH;
   356         public String getText() {
   357             return StringUtils.toLowerCase(name());
   358         }
   360         static final Map<String,Attr> index = new HashMap<String,Attr>();
   361         static {
   362             for (Attr t: values()) {
   363                 index.put(t.getText(), t);
   364             }
   365         }
   366     }
   368     public static enum AttrKind {
   369         INVALID,
   370         OBSOLETE,
   371         USE_CSS,
   372         OK
   373     }
   375     // This class exists to avoid warnings from using parameterized vararg type
   376     // Map<Attr,AttrKind> in signature of HtmlTag constructor.
   377     private static class AttrMap extends EnumMap<Attr,AttrKind>  {
   378         private static final long serialVersionUID = 0;
   379         AttrMap() {
   380             super(Attr.class);
   381         }
   382     }
   385     public final BlockType blockType;
   386     public final EndKind endKind;
   387     public final Set<Flag> flags;
   388     private final Map<Attr,AttrKind> attrs;
   390     HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
   391         this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
   392     }
   394     HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
   395         this.blockType = blockType;
   396         this.endKind = endKind;
   397         this.flags = flags;
   398         this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
   399         for (Map<Attr,AttrKind> m: attrMaps)
   400             this.attrs.putAll(m);
   401         attrs.put(Attr.CLASS, AttrKind.OK);
   402         attrs.put(Attr.ID, AttrKind.OK);
   403         attrs.put(Attr.STYLE, AttrKind.OK);
   404     }
   406     public boolean accepts(HtmlTag t) {
   407         if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
   408             return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
   409         } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
   410             return (t.blockType == BlockType.BLOCK);
   411         } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
   412             return (t.blockType == BlockType.INLINE);
   413         } else
   414             switch (blockType) {
   415                 case BLOCK:
   416                 case INLINE:
   417                     return (t.blockType == BlockType.INLINE);
   418                 case OTHER:
   419                     // OTHER tags are invalid in doc comments, and will be
   420                     // reported separately, so silently accept/ignore any content
   421                     return true;
   422                 default:
   423                     // any combination which could otherwise arrive here
   424                     // ought to have been handled in an overriding method
   425                     throw new AssertionError(this + ":" + t);
   426             }
   427     }
   429     public boolean acceptsText() {
   430         // generally, anywhere we can put text we can also put inline tag
   431         // so check if a typical inline tag is allowed
   432         return accepts(B);
   433     }
   435     public String getText() {
   436         return StringUtils.toLowerCase(name());
   437     }
   439     public Attr getAttr(Name attrName) {
   440         return Attr.index.get(StringUtils.toLowerCase(attrName.toString()));
   441     }
   443     public AttrKind getAttrKind(Name attrName) {
   444         AttrKind k = attrs.get(getAttr(attrName)); // null-safe
   445         return (k == null) ? AttrKind.INVALID : k;
   446     }
   448     private static AttrMap attrs(AttrKind k, Attr... attrs) {
   449         AttrMap map = new AttrMap();
   450         for (Attr a: attrs) map.put(a, k);
   451         return map;
   452     }
   454     private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
   455     static {
   456         for (HtmlTag t: values()) {
   457             index.put(t.getText(), t);
   458         }
   459     }
   461     static HtmlTag get(Name tagName) {
   462         return index.get(StringUtils.toLowerCase(tagName.toString()));
   463     }
   465 }

mercurial