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

changeset 1507
967052c425a1
parent 1506
4a3cfc970c6f
child 1552
153d20d0cac5
     1.1 --- a/src/share/classes/com/sun/tools/doclint/Checker.java	Mon Jan 21 10:00:46 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/doclint/Checker.java	Mon Jan 21 10:07:37 2013 -0800
     1.3 @@ -95,7 +95,8 @@
     1.4      public enum Flag {
     1.5          TABLE_HAS_CAPTION,
     1.6          HAS_ELEMENT,
     1.7 -        HAS_TEXT
     1.8 +        HAS_TEXT,
     1.9 +        REPORTED_BAD_INLINE
    1.10      }
    1.11  
    1.12      static class TagStackItem {
    1.13 @@ -195,7 +196,8 @@
    1.14  
    1.15      @Override
    1.16      public Void visitText(TextTree tree, Void ignore) {
    1.17 -        if (!tree.getBody().trim().isEmpty()) {
    1.18 +        if (hasNonWhitespace(tree)) {
    1.19 +            checkAllowsText(tree);
    1.20              markEnclosingTag(Flag.HAS_TEXT);
    1.21          }
    1.22          return null;
    1.23 @@ -203,6 +205,7 @@
    1.24  
    1.25      @Override
    1.26      public Void visitEntity(EntityTree tree, Void ignore) {
    1.27 +        checkAllowsText(tree);
    1.28          markEnclosingTag(Flag.HAS_TEXT);
    1.29          String name = tree.getName().toString();
    1.30          if (name.startsWith("#")) {
    1.31 @@ -218,6 +221,18 @@
    1.32          return null;
    1.33      }
    1.34  
    1.35 +    void checkAllowsText(DocTree tree) {
    1.36 +        TagStackItem top = tagStack.peek();
    1.37 +        if (top != null
    1.38 +                && top.tree.getKind() == DocTree.Kind.START_ELEMENT
    1.39 +                && !top.tag.acceptsText()) {
    1.40 +            if (top.flags.add(Flag.REPORTED_BAD_INLINE)) {
    1.41 +                env.messages.error(HTML, tree, "dc.text.not.allowed",
    1.42 +                        ((StartElementTree) top.tree).getName());
    1.43 +            }
    1.44 +        }
    1.45 +    }
    1.46 +
    1.47      // </editor-fold>
    1.48  
    1.49      // <editor-fold defaultstate="collapsed" desc="HTML elements">
    1.50 @@ -230,53 +245,22 @@
    1.51          if (t == null) {
    1.52              env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
    1.53          } else {
    1.54 +            for (TagStackItem tsi: tagStack) {
    1.55 +                if (tsi.tag.accepts(t)) {
    1.56 +                    while (tagStack.peek() != tsi) tagStack.pop();
    1.57 +                    break;
    1.58 +                } else if (tsi.tag.endKind != HtmlTag.EndKind.OPTIONAL)
    1.59 +                    break;
    1.60 +            }
    1.61 +
    1.62 +            checkStructure(tree, t);
    1.63 +
    1.64              // tag specific checks
    1.65              switch (t) {
    1.66                  // check for out of sequence headers, such as <h1>...</h1>  <h3>...</h3>
    1.67                  case H1: case H2: case H3: case H4: case H5: case H6:
    1.68                      checkHeader(tree, t);
    1.69                      break;
    1.70 -                // <p> inside <pre>
    1.71 -                case P:
    1.72 -                    TagStackItem top = tagStack.peek();
    1.73 -                    if (top != null && top.tag == HtmlTag.PRE)
    1.74 -                        env.messages.warning(HTML, tree, "dc.tag.p.in.pre");
    1.75 -                    break;
    1.76 -            }
    1.77 -
    1.78 -            // check that only block tags and inline tags are used,
    1.79 -            // and that blocks tags are not used within inline tags
    1.80 -            switch (t.blockType) {
    1.81 -                case INLINE:
    1.82 -                    break;
    1.83 -                case BLOCK:
    1.84 -                    TagStackItem top = tagStack.peek();
    1.85 -                    if (top != null && top.tag != null && top.tag.blockType == HtmlTag.BlockType.INLINE) {
    1.86 -                        switch (top.tree.getKind()) {
    1.87 -                            case START_ELEMENT: {
    1.88 -                                Name name = ((StartElementTree) top.tree).getName();
    1.89 -                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
    1.90 -                                        treeName, name);
    1.91 -                                break;
    1.92 -                            }
    1.93 -                            case LINK:
    1.94 -                            case LINK_PLAIN: {
    1.95 -                                String name = top.tree.getKind().tagName;
    1.96 -                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
    1.97 -                                        treeName, name);
    1.98 -                                break;
    1.99 -                            }
   1.100 -                            default:
   1.101 -                                env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.other",
   1.102 -                                        treeName);
   1.103 -                        }
   1.104 -                    }
   1.105 -                    break;
   1.106 -                case OTHER:
   1.107 -                    env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
   1.108 -                    break;
   1.109 -                default:
   1.110 -                    throw new AssertionError();
   1.111              }
   1.112  
   1.113              if (t.flags.contains(HtmlTag.Flag.NO_NEST)) {
   1.114 @@ -324,6 +308,58 @@
   1.115          }
   1.116      }
   1.117  
   1.118 +    private void checkStructure(StartElementTree tree, HtmlTag t) {
   1.119 +        Name treeName = tree.getName();
   1.120 +        TagStackItem top = tagStack.peek();
   1.121 +        switch (t.blockType) {
   1.122 +            case BLOCK:
   1.123 +                if (top == null || top.tag.accepts(t))
   1.124 +                    return;
   1.125 +
   1.126 +                switch (top.tree.getKind()) {
   1.127 +                    case START_ELEMENT: {
   1.128 +                        if (top.tag.blockType == HtmlTag.BlockType.INLINE) {
   1.129 +                            Name name = ((StartElementTree) top.tree).getName();
   1.130 +                            env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
   1.131 +                                    treeName, name);
   1.132 +                            return;
   1.133 +                        }
   1.134 +                    }
   1.135 +                    break;
   1.136 +
   1.137 +                    case LINK:
   1.138 +                    case LINK_PLAIN: {
   1.139 +                        String name = top.tree.getKind().tagName;
   1.140 +                        env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
   1.141 +                                treeName, name);
   1.142 +                        return;
   1.143 +                    }
   1.144 +                }
   1.145 +                break;
   1.146 +
   1.147 +            case INLINE:
   1.148 +                if (top == null || top.tag.accepts(t))
   1.149 +                    return;
   1.150 +                break;
   1.151 +
   1.152 +            case LIST_ITEM:
   1.153 +            case TABLE_ITEM:
   1.154 +                if (top != null) {
   1.155 +                    // reset this flag so subsequent bad inline content gets reported
   1.156 +                    top.flags.remove(Flag.REPORTED_BAD_INLINE);
   1.157 +                    if (top.tag.accepts(t))
   1.158 +                        return;
   1.159 +                }
   1.160 +                break;
   1.161 +
   1.162 +            case OTHER:
   1.163 +                env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
   1.164 +                return;
   1.165 +        }
   1.166 +
   1.167 +        env.messages.error(HTML, tree, "dc.tag.not.allowed.here", treeName);
   1.168 +    }
   1.169 +
   1.170      private void checkHeader(StartElementTree tree, HtmlTag tag) {
   1.171          // verify the new tag
   1.172          if (getHeaderLevel(tag) > getHeaderLevel(currHeaderTag) + 1) {
   1.173 @@ -378,10 +414,6 @@
   1.174                              && !top.flags.contains(Flag.HAS_ELEMENT)) {
   1.175                          env.messages.warning(HTML, tree, "dc.tag.empty", treeName);
   1.176                      }
   1.177 -                    if (t.flags.contains(HtmlTag.Flag.NO_TEXT)
   1.178 -                            && top.flags.contains(Flag.HAS_TEXT)) {
   1.179 -                        env.messages.error(HTML, tree, "dc.text.not.allowed", treeName);
   1.180 -                    }
   1.181                      tagStack.pop();
   1.182                      done = true;
   1.183                      break;
   1.184 @@ -763,7 +795,7 @@
   1.185          for (DocTree d: list) {
   1.186              switch (d.getKind()) {
   1.187                  case TEXT:
   1.188 -                    if (!((TextTree) d).getBody().trim().isEmpty())
   1.189 +                    if (hasNonWhitespace((TextTree) d))
   1.190                          return;
   1.191                      break;
   1.192                  default:
   1.193 @@ -772,6 +804,16 @@
   1.194          }
   1.195          env.messages.warning(SYNTAX, tree, "dc.empty", tree.getKind().tagName);
   1.196      }
   1.197 +
   1.198 +    boolean hasNonWhitespace(TextTree tree) {
   1.199 +        String s = tree.getBody();
   1.200 +        for (int i = 0; i < s.length(); i++) {
   1.201 +            if (!Character.isWhitespace(s.charAt(i)))
   1.202 +                return true;
   1.203 +        }
   1.204 +        return false;
   1.205 +    }
   1.206 +
   1.207      // </editor-fold>
   1.208  
   1.209  }

mercurial