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

Thu, 28 Feb 2013 14:00:52 +0000

author
mcimadamore
date
Thu, 28 Feb 2013 14:00:52 +0000
changeset 1608
133a0a0c2cbc
parent 1507
967052c425a1
child 1793
391f97e270c2
permissions
-rw-r--r--

8008723: Graph Inference: bad graph calculation leads to assertion error
Summary: Dependencies are not propagated correctly through merged nodes during inference graph initialization
Reviewed-by: jjg

     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)),
   136     LINK(BlockType.OTHER, EndKind.NONE),
   138     MENU(BlockType.BLOCK, EndKind.REQUIRED) {
   139         @Override
   140         public boolean accepts(HtmlTag t) {
   141             return (t == LI);
   142         }
   143     },
   145     META(BlockType.OTHER, EndKind.NONE),
   147     NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
   149     NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
   151     OL(BlockType.BLOCK, EndKind.REQUIRED,
   152             EnumSet.of(Flag.EXPECT_CONTENT),
   153             attrs(AttrKind.USE_CSS, START, TYPE)){
   154         @Override
   155         public boolean accepts(HtmlTag t) {
   156             return (t == LI);
   157         }
   158     },
   160     P(BlockType.BLOCK, EndKind.OPTIONAL,
   161             EnumSet.of(Flag.EXPECT_CONTENT),
   162             attrs(AttrKind.USE_CSS, ALIGN)),
   164     PRE(BlockType.BLOCK, EndKind.REQUIRED,
   165             EnumSet.of(Flag.EXPECT_CONTENT)) {
   166         @Override
   167         public boolean accepts(HtmlTag t) {
   168             switch (t) {
   169                 case IMG: case BIG: case SMALL: case SUB: case SUP:
   170                     return false;
   171                 default:
   172                     return (t.blockType == BlockType.INLINE);
   173             }
   174         }
   175     },
   177     SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
   179     SMALL(BlockType.INLINE, EndKind.REQUIRED,
   180             EnumSet.of(Flag.EXPECT_CONTENT)),
   182     SPAN(BlockType.INLINE, EndKind.REQUIRED,
   183             EnumSet.of(Flag.EXPECT_CONTENT)),
   185     STRONG(BlockType.INLINE, EndKind.REQUIRED,
   186             EnumSet.of(Flag.EXPECT_CONTENT)),
   188     SUB(BlockType.INLINE, EndKind.REQUIRED,
   189             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   191     SUP(BlockType.INLINE, EndKind.REQUIRED,
   192             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   194     TABLE(BlockType.BLOCK, EndKind.REQUIRED,
   195             EnumSet.of(Flag.EXPECT_CONTENT),
   196             attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
   197                 CELLPADDING, CELLSPACING),
   198             attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)) {
   199         @Override
   200         public boolean accepts(HtmlTag t) {
   201             switch (t) {
   202                 case CAPTION:
   203                 case THEAD: case TBODY: case TFOOT:
   204                 case TR: // HTML 3.2
   205                     return true;
   206                 default:
   207                     return false;
   208             }
   209         }
   210     },
   212     TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   213             EnumSet.of(Flag.EXPECT_CONTENT),
   214             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   215         @Override
   216         public boolean accepts(HtmlTag t) {
   217             return (t == TR);
   218         }
   219     },
   221     TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   222             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   223             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   224                 ALIGN, CHAR, CHAROFF, VALIGN),
   225             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   227     TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   228             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   229         @Override
   230         public boolean accepts(HtmlTag t) {
   231             return (t == TR);
   232         }
   233     },
   235     TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   236             EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
   237             attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
   238                 ALIGN, CHAR, CHAROFF, VALIGN),
   239             attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
   241     THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
   242             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
   243         @Override
   244         public boolean accepts(HtmlTag t) {
   245             return (t == TR);
   246         }
   247     },
   249     TITLE(BlockType.OTHER, EndKind.REQUIRED),
   251     TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
   252             attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
   253             attrs(AttrKind.USE_CSS, BGCOLOR)) {
   254         @Override
   255         public boolean accepts(HtmlTag t) {
   256             return (t == TH) || (t == TD);
   257         }
   258     },
   260     TT(BlockType.INLINE, EndKind.REQUIRED,
   261             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   263     U(BlockType.INLINE, EndKind.REQUIRED,
   264             EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
   266     UL(BlockType.BLOCK, EndKind.REQUIRED,
   267             EnumSet.of(Flag.EXPECT_CONTENT),
   268             attrs(AttrKind.USE_CSS, COMPACT, TYPE)){
   269         @Override
   270         public boolean accepts(HtmlTag t) {
   271             return (t == LI);
   272         }
   273     },
   275     VAR(BlockType.INLINE, EndKind.REQUIRED);
   277     /**
   278      * Enum representing the type of HTML element.
   279      */
   280     public static enum BlockType {
   281         BLOCK,
   282         INLINE,
   283         LIST_ITEM,
   284         TABLE_ITEM,
   285         OTHER;
   286     }
   288     /**
   289      * Enum representing HTML end tag requirement.
   290      */
   291     public static enum EndKind {
   292         NONE,
   293         OPTIONAL,
   294         REQUIRED;
   295     }
   297     public static enum Flag {
   298         ACCEPTS_BLOCK,
   299         ACCEPTS_INLINE,
   300         EXPECT_CONTENT,
   301         NO_NEST
   302     }
   304     public static enum Attr {
   305         ABBR,
   306         ALIGN,
   307         ALT,
   308         AXIS,
   309         BGCOLOR,
   310         BORDER,
   311         CELLSPACING,
   312         CELLPADDING,
   313         CHAR,
   314         CHAROFF,
   315         CLEAR,
   316         CLASS,
   317         COLOR,
   318         COLSPAN,
   319         COMPACT,
   320         FACE,
   321         FRAME,
   322         HEADERS,
   323         HEIGHT,
   324         HREF,
   325         HSPACE,
   326         ID,
   327         NAME,
   328         NOWRAP,
   329         REVERSED,
   330         ROWSPAN,
   331         RULES,
   332         SCOPE,
   333         SIZE,
   334         SPACE,
   335         SRC,
   336         START,
   337         STYLE,
   338         SUMMARY,
   339         TARGET,
   340         TYPE,
   341         VALIGN,
   342         VSPACE,
   343         WIDTH;
   345         public String getText() {
   346             return name().toLowerCase();
   347         }
   349         static final Map<String,Attr> index = new HashMap<String,Attr>();
   350         static {
   351             for (Attr t: values()) {
   352                 index.put(t.getText(), t);
   353             }
   354         }
   355     }
   357     public static enum AttrKind {
   358         INVALID,
   359         OBSOLETE,
   360         USE_CSS,
   361         OK
   362     }
   364     // This class exists to avoid warnings from using parameterized vararg type
   365     // Map<Attr,AttrKind> in signature of HtmlTag constructor.
   366     private static class AttrMap extends EnumMap<Attr,AttrKind>  {
   367         private static final long serialVersionUID = 0;
   368         AttrMap() {
   369             super(Attr.class);
   370         }
   371     }
   374     public final BlockType blockType;
   375     public final EndKind endKind;
   376     public final Set<Flag> flags;
   377     private final Map<Attr,AttrKind> attrs;
   379     HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
   380         this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
   381     }
   383     HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
   384         this.blockType = blockType;
   385         this.endKind = endKind;
   386         this.flags = flags;
   387         this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
   388         for (Map<Attr,AttrKind> m: attrMaps)
   389             this.attrs.putAll(m);
   390         attrs.put(Attr.CLASS, AttrKind.OK);
   391         attrs.put(Attr.ID, AttrKind.OK);
   392         attrs.put(Attr.STYLE, AttrKind.OK);
   393     }
   395     public boolean accepts(HtmlTag t) {
   396         if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
   397             return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
   398         } else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
   399             return (t.blockType == BlockType.BLOCK);
   400         } else if (flags.contains(Flag.ACCEPTS_INLINE)) {
   401             return (t.blockType == BlockType.INLINE);
   402         } else
   403             switch (blockType) {
   404                 case BLOCK:
   405                 case INLINE:
   406                     return (t.blockType == BlockType.INLINE);
   407                 case OTHER:
   408                     // OTHER tags are invalid in doc comments, and will be
   409                     // reported separately, so silently accept/ignore any content
   410                     return true;
   411                 default:
   412                     // any combination which could otherwise arrive here
   413                     // ought to have been handled in an overriding method
   414                     throw new AssertionError(this + ":" + t);
   415             }
   416     }
   418     public boolean acceptsText() {
   419         // generally, anywhere we can put text we can also put inline tag
   420         // so check if a typical inline tag is allowed
   421         return accepts(B);
   422     }
   424     public String getText() {
   425         return name().toLowerCase();
   426     }
   428     public Attr getAttr(Name attrName) {
   429         return Attr.index.get(attrName.toString().toLowerCase());
   430     }
   432     public AttrKind getAttrKind(Name attrName) {
   433         AttrKind k = attrs.get(getAttr(attrName)); // null-safe
   434         return (k == null) ? AttrKind.INVALID : k;
   435     }
   437     private static AttrMap attrs(AttrKind k, Attr... attrs) {
   438         AttrMap map = new AttrMap();
   439         for (Attr a: attrs) map.put(a, k);
   440         return map;
   441     }
   443     private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
   444     static {
   445         for (HtmlTag t: values()) {
   446             index.put(t.getText(), t);
   447         }
   448     }
   450     static HtmlTag get(Name tagName) {
   451         return index.get(tagName.toString().toLowerCase());
   452     }
   453 }

mercurial