mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 03:43:21 +00:00
8300914: Allow @ as an escape in documentation comments
Reviewed-by: prappo
This commit is contained in:
parent
8a9e383dba
commit
873558ee80
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -103,6 +103,14 @@ public interface DocTree {
|
||||
*/
|
||||
ERRONEOUS,
|
||||
|
||||
/**
|
||||
* Used for instances of {@link EscapeTree}
|
||||
* representing some escaped documentation text.
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
ESCAPE,
|
||||
|
||||
/**
|
||||
* Used for instances of {@link ThrowsTree}
|
||||
* representing an {@code @exception} tag.
|
||||
@ -250,7 +258,7 @@ public interface DocTree {
|
||||
|
||||
/**
|
||||
* Used for instances of {@link TextTree}
|
||||
* representing some documentation text.
|
||||
* representing some plain documentation text.
|
||||
*/
|
||||
TEXT,
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -143,6 +143,22 @@ public interface DocTreeVisitor<R,P> {
|
||||
*/
|
||||
R visitErroneous(ErroneousTree node, P p);
|
||||
|
||||
/**
|
||||
* Visits an {@code EscapeTree} node.
|
||||
*
|
||||
* @implSpec Visits the provided {@code EscapeTree} node
|
||||
* by calling {@code visitOther(node, p)}.
|
||||
*
|
||||
* @param node the node being visited
|
||||
* @param p a parameter value
|
||||
* @return a result value
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
default R visitEscape(EscapeTree node, P p) {
|
||||
return visitOther(node, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a {@code HiddenTree} node.
|
||||
*
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.source.doctree;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.util.Elements;
|
||||
|
||||
/**
|
||||
* A tree node for a character represented by an escape sequence.
|
||||
*
|
||||
* @apiNote This class does not itself constrain the set of valid escape sequences,
|
||||
* although the set may be effectively constrained to those defined in the
|
||||
* <a href="{@docRoot}/../specs/javadoc/doc-comment-spec.html#escape-sequences">
|
||||
* Documentation Comment Specification for the Standard Doclet</a>,
|
||||
* including the following context-sensitive escape sequences:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code @@}, representing {@code @}, where it would otherwise be treated as introducing a block or inline tag,
|
||||
* <li>{@code @/}, representing {@code /}, as part of {@code *@/} to represent <code>*/</code>, and
|
||||
* <li>{@code @*}, representing {@code *}, where it would otherwise be {@linkplain Elements#getDocComment(Element) discarded},
|
||||
* after whitespace at the beginning of a line.
|
||||
* </ul>
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
public interface EscapeTree extends TextTree {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>Note: this method returns the escaped character, not the original escape sequence.
|
||||
*/
|
||||
@Override
|
||||
String getBody();
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,9 @@ package com.sun.source.util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
|
||||
@ -43,6 +45,7 @@ import com.sun.source.doctree.DocTypeTree;
|
||||
import com.sun.source.doctree.EndElementTree;
|
||||
import com.sun.source.doctree.EntityTree;
|
||||
import com.sun.source.doctree.ErroneousTree;
|
||||
import com.sun.source.doctree.EscapeTree;
|
||||
import com.sun.source.doctree.HiddenTree;
|
||||
import com.sun.source.doctree.IdentifierTree;
|
||||
import com.sun.source.doctree.IndexTree;
|
||||
@ -175,6 +178,29 @@ public interface DocTreeFactory {
|
||||
*/
|
||||
ErroneousTree newErroneousTree(String text, Diagnostic<JavaFileObject> diag);
|
||||
|
||||
/**
|
||||
* Creates a new {@code EscapeTree} object, to represent an escaped character.
|
||||
*
|
||||
* @apiNote This method does not itself constrain the set of valid escape sequences,
|
||||
* although the set may be effectively constrained to those defined in the
|
||||
* <a href="{@docRoot}/../specs/javadoc/doc-comment-spec.html#escape-sequences">
|
||||
* Documentation Comment Specification for the Standard Doclet</a>,
|
||||
* including the following context-sensitive escape sequences:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code @@}, representing {@code @}, where it would otherwise be treated as introducing a block or inline tag,
|
||||
* <li>{@code @/}, representing {@code /}, as part of {@code *@/} to represent <code>*/</code>, and
|
||||
* <li>{@code @*}, representing {@code *}, where it would otherwise be {@linkplain Elements#getDocComment(Element) discarded},
|
||||
* after whitespace at the beginning of a line.
|
||||
* </ul>
|
||||
*
|
||||
* @param ch the character
|
||||
* @return an {@code EscapeTree} object
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
EscapeTree newEscapeTree(char ch);
|
||||
|
||||
/**
|
||||
* Creates a new {@code ThrowsTree} object, to represent an {@code @exception} tag.
|
||||
* @param name the name of the exception
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -277,6 +277,22 @@ public class DocTreeScanner<R,P> implements DocTreeVisitor<R,P> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec This implementation returns {@code null}.
|
||||
*
|
||||
* @param node {@inheritDoc}
|
||||
* @param p {@inheritDoc}
|
||||
* @return the result of scanning
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
@Override
|
||||
public R visitEscape(EscapeTree node, P p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -232,6 +232,22 @@ public class SimpleDocTreeVisitor<R,P> implements DocTreeVisitor<R, P> {
|
||||
return defaultAction(node, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec This implementation calls {@code defaultAction}.
|
||||
*
|
||||
* @param node {@inheritDoc}
|
||||
* @param p {@inheritDoc}
|
||||
* @return the result of {@code defaultAction}
|
||||
*
|
||||
* @since 21
|
||||
*/
|
||||
@Override
|
||||
public R visitEscape(EscapeTree node, P p) {
|
||||
return defaultAction(node, p);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
|
||||
@ -152,6 +152,10 @@ public class DocCommentParser {
|
||||
}
|
||||
}
|
||||
|
||||
char peekChar() {
|
||||
return buf[bp < buflen ? bp + 1 : buflen];
|
||||
}
|
||||
|
||||
protected List<DCTree> blockContent() {
|
||||
return blockContent(Phase.BODY);
|
||||
}
|
||||
@ -224,9 +228,32 @@ public class DocCommentParser {
|
||||
break;
|
||||
|
||||
case '@':
|
||||
// check for context-sensitive escape sequences:
|
||||
// newline whitespace @@
|
||||
// newline whitespace @*
|
||||
// *@/
|
||||
if (newline) {
|
||||
addPendingText(trees, lastNonWhite);
|
||||
break loop;
|
||||
char peek = peekChar();
|
||||
if (peek == '@' || peek == '*') {
|
||||
addPendingText(trees, bp - 1);
|
||||
nextChar();
|
||||
trees.add(m.at(bp - 1).newEscapeTree(ch));
|
||||
newline = false;
|
||||
nextChar();
|
||||
textStart = bp;
|
||||
break;
|
||||
} else {
|
||||
addPendingText(trees, lastNonWhite);
|
||||
break loop;
|
||||
}
|
||||
} else if (textStart != -1 && buf[bp - 1] == '*' && peekChar() == '/') {
|
||||
addPendingText(trees, bp - 1);
|
||||
nextChar();
|
||||
trees.add(m.at(bp - 1).newEscapeTree('/'));
|
||||
newline = false;
|
||||
nextChar();
|
||||
textStart = bp;
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
@ -294,10 +321,24 @@ public class DocCommentParser {
|
||||
newline = false;
|
||||
nextChar();
|
||||
if (ch == '@') {
|
||||
addPendingText(list, bp - 2);
|
||||
list.add(inlineTag());
|
||||
textStart = bp;
|
||||
lastNonWhite = -1;
|
||||
// check for context-sensitive escape-sequence
|
||||
// {@@
|
||||
if (peekChar() == '@') {
|
||||
if (textStart == -1) {
|
||||
textStart = bp - 1;
|
||||
}
|
||||
addPendingText(list, bp - 1);
|
||||
nextChar();
|
||||
list.add(m.at(bp - 1).newEscapeTree('@'));
|
||||
nextChar();
|
||||
textStart = -1;
|
||||
lastNonWhite = bp;
|
||||
} else {
|
||||
addPendingText(list, bp - 2);
|
||||
list.add(inlineTag());
|
||||
textStart = bp;
|
||||
lastNonWhite = -1;
|
||||
}
|
||||
} else {
|
||||
if (textStart == -1)
|
||||
textStart = bp - 1;
|
||||
@ -624,6 +665,33 @@ public class DocCommentParser {
|
||||
nextChar();
|
||||
break;
|
||||
|
||||
case '@':
|
||||
// check for context-sensitive escape sequences:
|
||||
// newline whitespace @@
|
||||
// newline whitespace @*
|
||||
// *@/
|
||||
if (newline) {
|
||||
char peek = peekChar();
|
||||
if (peek == '@' || peek == '*') {
|
||||
addPendingText(trees, bp - 1);
|
||||
nextChar();
|
||||
trees.add(m.at(bp - 1).newEscapeTree(ch));
|
||||
newline = false;
|
||||
nextChar();
|
||||
textStart = bp;
|
||||
break;
|
||||
}
|
||||
} else if (textStart != -1 && buf[bp - 1] == '*' && peekChar() == '/') {
|
||||
addPendingText(trees, bp - 1);
|
||||
nextChar();
|
||||
trees.add(m.at(bp - 1).newEscapeTree('/'));
|
||||
newline = false;
|
||||
nextChar();
|
||||
textStart = bp;
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
|
||||
default:
|
||||
if (textStart == -1)
|
||||
textStart = bp;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -168,6 +168,11 @@ public abstract class DCTree implements DocTree {
|
||||
return err.pos + err.body.length();
|
||||
}
|
||||
|
||||
case ESCAPE -> {
|
||||
DCEscape esc = (DCEscape) this;
|
||||
return esc.pos + 2;
|
||||
}
|
||||
|
||||
case IDENTIFIER -> {
|
||||
DCIdentifier ident = (DCIdentifier) this;
|
||||
return ident.pos + ident.name.length();
|
||||
@ -641,7 +646,29 @@ public abstract class DCTree implements DocTree {
|
||||
this.prefPos = prefPos;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DCEscape extends DCTree implements EscapeTree {
|
||||
public final char ch;
|
||||
|
||||
DCEscape(char ch) {
|
||||
this.ch = ch;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Kind getKind() {
|
||||
return Kind.ESCAPE;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public <R, D> R accept(DocTreeVisitor<R, D> v, D d) {
|
||||
return v.visitEscape(this, d);
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public String getBody() {
|
||||
return String.valueOf(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DCHidden extends DCBlockTag implements HiddenTree {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -245,6 +245,17 @@ public class DocPretty implements DocTreeVisitor<Void,Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Void visitEscape(EscapeTree node, Void p) {
|
||||
try {
|
||||
out.write("@");
|
||||
print(node.getBody());
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Void visitHidden(HiddenTree node, Void p) {
|
||||
try {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -60,6 +60,7 @@ import com.sun.tools.javac.tree.DCTree.DCDocType;
|
||||
import com.sun.tools.javac.tree.DCTree.DCEndElement;
|
||||
import com.sun.tools.javac.tree.DCTree.DCEntity;
|
||||
import com.sun.tools.javac.tree.DCTree.DCErroneous;
|
||||
import com.sun.tools.javac.tree.DCTree.DCEscape;
|
||||
import com.sun.tools.javac.tree.DCTree.DCHidden;
|
||||
import com.sun.tools.javac.tree.DCTree.DCIdentifier;
|
||||
import com.sun.tools.javac.tree.DCTree.DCIndex;
|
||||
@ -276,6 +277,13 @@ public class DocTreeMaker implements DocTreeFactory {
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public DCEscape newEscapeTree(char ch) {
|
||||
DCEscape tree = new DCEscape(ch);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public DCThrows newExceptionTree(ReferenceTree name, List<? extends DocTree> description) {
|
||||
// TODO: verify the reference is just to a type (not a field or method)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,6 +48,7 @@ import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.EndElementTree;
|
||||
import com.sun.source.doctree.EntityTree;
|
||||
import com.sun.source.doctree.EscapeTree;
|
||||
import com.sun.source.doctree.InlineTagTree;
|
||||
import com.sun.source.doctree.LinkTree;
|
||||
import com.sun.source.doctree.LiteralTree;
|
||||
@ -218,6 +219,12 @@ public class JavadocFormatter {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Object visitEscape(EscapeTree node, Object p) {
|
||||
result.append(node.getBody());
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Object visitLink(LinkTree node, Object p) {
|
||||
if (!node.getLabel().isEmpty()) {
|
||||
|
||||
@ -67,6 +67,7 @@ import com.sun.source.doctree.DocTree.Kind;
|
||||
import com.sun.source.doctree.EndElementTree;
|
||||
import com.sun.source.doctree.EntityTree;
|
||||
import com.sun.source.doctree.ErroneousTree;
|
||||
import com.sun.source.doctree.EscapeTree;
|
||||
import com.sun.source.doctree.IndexTree;
|
||||
import com.sun.source.doctree.InheritDocTree;
|
||||
import com.sun.source.doctree.LinkTree;
|
||||
@ -1338,6 +1339,12 @@ public class HtmlDocletWriter {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitEscape(EscapeTree node, Content content) {
|
||||
result.add(node.getBody());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitInheritDoc(InheritDocTree node, Content content) {
|
||||
Content output = getInlineTagOutput(element, node, context);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -31,6 +31,7 @@ import com.sun.source.doctree.CommentTree;
|
||||
import com.sun.source.doctree.DeprecatedTree;
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.EscapeTree;
|
||||
import com.sun.source.doctree.IdentifierTree;
|
||||
import com.sun.source.doctree.InlineTagTree;
|
||||
import com.sun.source.doctree.LinkTree;
|
||||
@ -386,6 +387,11 @@ public class CommentHelper {
|
||||
return node.getBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends DocTree> visitEscape(EscapeTree node, Void p) {
|
||||
return asList(node.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends DocTree> visitLiteral(LiteralTree node, Void p) {
|
||||
return asList(node.getBody().getBody());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -65,6 +65,7 @@ import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.EndElementTree;
|
||||
import com.sun.source.doctree.EntityTree;
|
||||
import com.sun.source.doctree.ErroneousTree;
|
||||
import com.sun.source.doctree.EscapeTree;
|
||||
import com.sun.source.doctree.IdentifierTree;
|
||||
import com.sun.source.doctree.IndexTree;
|
||||
import com.sun.source.doctree.InheritDocTree;
|
||||
@ -348,6 +349,7 @@ public class Checker extends DocTreePathScanner<Void, Void> {
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Void visitEntity(EntityTree tree, Void ignore) {
|
||||
hasNonWhitespaceText = true;
|
||||
checkAllowsText(tree);
|
||||
markEnclosingTag(Flag.HAS_TEXT);
|
||||
String s = env.trees.getCharacters(tree);
|
||||
@ -358,6 +360,14 @@ public class Checker extends DocTreePathScanner<Void, Void> {
|
||||
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Void visitEscape(EscapeTree tree, Void ignore) {
|
||||
hasNonWhitespaceText = true;
|
||||
checkAllowsText(tree);
|
||||
markEnclosingTag(Flag.HAS_TEXT);
|
||||
return null;
|
||||
}
|
||||
|
||||
void checkAllowsText(DocTree tree) {
|
||||
TagStackItem top = tagStack.peek();
|
||||
if (top != null
|
||||
|
||||
@ -66,6 +66,14 @@ public class HtmlTagsTest {
|
||||
*/
|
||||
public void inline_not_allowed() { }
|
||||
|
||||
/**
|
||||
* <ul> & <li> ... </li> </ul>
|
||||
*/
|
||||
public void entity_not_allowed() { }
|
||||
|
||||
/**
|
||||
* <ul> *@/ <li> ... </li> </ul>
|
||||
*/
|
||||
public void escape_not_allowed() { }
|
||||
}
|
||||
|
||||
|
||||
@ -43,5 +43,11 @@ HtmlTagsTest.java:60: error: text not allowed in <ul> element
|
||||
HtmlTagsTest.java:65: error: tag not allowed here: <b>
|
||||
* <ul> <b>text</b> <li> ... </li> </ul>
|
||||
^
|
||||
13 errors
|
||||
HtmlTagsTest.java:70: error: text not allowed in <ul> element
|
||||
* <ul> & <li> ... </li> </ul>
|
||||
^
|
||||
HtmlTagsTest.java:75: error: text not allowed in <ul> element
|
||||
* <ul> *@/ <li> ... </li> </ul>
|
||||
^
|
||||
15 errors
|
||||
2 warnings
|
||||
|
||||
31
test/langtools/tools/doclint/ReturnTest.java
Normal file
31
test/langtools/tools/doclint/ReturnTest.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @modules jdk.javadoc/jdk.javadoc.internal.doclint
|
||||
* @build DocLintTester
|
||||
* @run main DocLintTester -ref ReturnTest.out ReturnTest.java
|
||||
*/
|
||||
|
||||
/** No comment. */
|
||||
public class ReturnTest {
|
||||
/**
|
||||
{@return legal} **/
|
||||
public int m_legal() { return 0; }
|
||||
|
||||
/** <p> {@return illegal} **/
|
||||
public int m_illegal_html() { return 0; }
|
||||
|
||||
/** text {@return illegal} **/
|
||||
public int m_illegal_text() { return 0; }
|
||||
|
||||
/** &{@return illegal} **/
|
||||
public int m_illegal_entity() { return 0; }
|
||||
|
||||
/** @@{@return illegal} **/
|
||||
public int m_illegal_escape() { return 0; }
|
||||
|
||||
/** {@return legal} text {@return illegal} **/
|
||||
public int m_illegal_repeat() { return 0; }
|
||||
|
||||
/** . */
|
||||
private ReturnTest() { }
|
||||
}
|
||||
19
test/langtools/tools/doclint/ReturnTest.out
Normal file
19
test/langtools/tools/doclint/ReturnTest.out
Normal file
@ -0,0 +1,19 @@
|
||||
ReturnTest.java:14: warning: {@return} not at beginning of description
|
||||
/** <p> {@return illegal} **/
|
||||
^
|
||||
ReturnTest.java:17: warning: {@return} not at beginning of description
|
||||
/** text {@return illegal} **/
|
||||
^
|
||||
ReturnTest.java:20: warning: {@return} not at beginning of description
|
||||
/** &{@return illegal} **/
|
||||
^
|
||||
ReturnTest.java:23: warning: {@return} not at beginning of description
|
||||
/** @@{@return illegal} **/
|
||||
^
|
||||
ReturnTest.java:26: warning: @return has already been specified
|
||||
/** {@return legal} text {@return illegal} **/
|
||||
^
|
||||
ReturnTest.java:26: warning: {@return} not at beginning of description
|
||||
/** {@return legal} text {@return illegal} **/
|
||||
^
|
||||
6 warnings
|
||||
@ -9,13 +9,22 @@
|
||||
public class SummaryTest {
|
||||
/**
|
||||
{@summary legal} **/
|
||||
public void m0() {}
|
||||
public void m_legal() {}
|
||||
|
||||
/** <p> {@summary illegal} **/
|
||||
public void m1() {}
|
||||
public void m_illegal_html() {}
|
||||
|
||||
/** text {@summary illegal} **/
|
||||
public void m_illegal_text() {}
|
||||
|
||||
/** &{@summary illegal} **/
|
||||
public void m_illegal_entity() {}
|
||||
|
||||
/** @@{@summary illegal} **/
|
||||
public void m_illegal_escape() {}
|
||||
|
||||
/** {@summary legal} text {@summary illegal} **/
|
||||
public void m2() {}
|
||||
public void m_illegal_repeat() {}
|
||||
|
||||
/** . */
|
||||
private SummaryTest() { }
|
||||
|
||||
@ -2,6 +2,15 @@ SummaryTest.java:14: warning: invalid use of @summary
|
||||
/** <p> {@summary illegal} **/
|
||||
^
|
||||
SummaryTest.java:17: warning: invalid use of @summary
|
||||
/** text {@summary illegal} **/
|
||||
^
|
||||
SummaryTest.java:20: warning: invalid use of @summary
|
||||
/** &{@summary illegal} **/
|
||||
^
|
||||
SummaryTest.java:23: warning: invalid use of @summary
|
||||
/** @@{@summary illegal} **/
|
||||
^
|
||||
SummaryTest.java:26: warning: invalid use of @summary
|
||||
/** {@summary legal} text {@summary illegal} **/
|
||||
^
|
||||
2 warnings
|
||||
5 warnings
|
||||
|
||||
148
test/langtools/tools/javac/doctree/AtEscapeTest.java
Normal file
148
test/langtools/tools/javac/doctree/AtEscapeTest.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8300914
|
||||
* @summary Allow `@` as an escape in documentation comments
|
||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||
* jdk.compiler/com.sun.tools.javac.file
|
||||
* jdk.compiler/com.sun.tools.javac.tree
|
||||
* jdk.compiler/com.sun.tools.javac.util
|
||||
* @build DocCommentTester
|
||||
* @run main DocCommentTester AtEscapeTest.java
|
||||
*/
|
||||
|
||||
class AtEscapeTest {
|
||||
/**
|
||||
* abc
|
||||
* @@tag
|
||||
* def
|
||||
*/
|
||||
void escape_block_tag() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 3
|
||||
Text[TEXT, pos:1, abc|_]
|
||||
Escape[ESCAPE, pos:6, @]
|
||||
Text[TEXT, pos:8, tag|_def]
|
||||
body: empty
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
/**
|
||||
* abc {@@tag} def
|
||||
*/
|
||||
void escape_inline_tag() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 3
|
||||
Text[TEXT, pos:1, abc_{]
|
||||
Escape[ESCAPE, pos:6, @]
|
||||
Text[TEXT, pos:8, tag}_def]
|
||||
body: empty
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
/**
|
||||
* abc /* def *@/ ghi
|
||||
*/
|
||||
void escape_end_comment() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 3
|
||||
Text[TEXT, pos:1, abc_/*_def_*]
|
||||
Escape[ESCAPE, pos:13, /]
|
||||
Text[TEXT, pos:15, _ghi]
|
||||
body: empty
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
/**
|
||||
abc
|
||||
@* def
|
||||
ghi
|
||||
*/
|
||||
void escape_asterisk() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:5
|
||||
firstSentence: 3
|
||||
Text[TEXT, pos:5, abc|_____]
|
||||
Escape[ESCAPE, pos:14, *]
|
||||
Text[TEXT, pos:16, _def|_____ghi]
|
||||
body: empty
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
/**
|
||||
* abc.
|
||||
* not an escaped tag @@tag;
|
||||
* xyz.
|
||||
*/
|
||||
void not_escaped_tag() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 1
|
||||
Text[TEXT, pos:1, abc.]
|
||||
body: 1
|
||||
Text[TEXT, pos:7, not_an_escaped_tag_@@tag;|_xyz.]
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
/**
|
||||
* abc.
|
||||
* not an escaped asterisk @*;
|
||||
* xyz.
|
||||
*/
|
||||
void not_escaped_asterisk() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 1
|
||||
Text[TEXT, pos:1, abc.]
|
||||
body: 1
|
||||
Text[TEXT, pos:7, not_an_escaped_asterisk_@*;|_xyz.]
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
/**
|
||||
* abc.
|
||||
* not an escaped solidus @/.
|
||||
* xyz.
|
||||
*/
|
||||
void not_escaped_solidus() { }
|
||||
/*
|
||||
DocComment[DOC_COMMENT, pos:1
|
||||
firstSentence: 1
|
||||
Text[TEXT, pos:1, abc.]
|
||||
body: 1
|
||||
Text[TEXT, pos:7, not_an_escaped_solidus_@/.|_xyz.]
|
||||
block tags: empty
|
||||
]
|
||||
*/
|
||||
|
||||
}
|
||||
@ -462,6 +462,11 @@ public class DocCommentTester {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitEscape(EscapeTree node, Void p) {
|
||||
header(node, node.getBody());
|
||||
return null;
|
||||
}
|
||||
|
||||
public Void visitHidden(HiddenTree node, Void p) {
|
||||
header(node);
|
||||
indent(+1);
|
||||
@ -933,7 +938,7 @@ public class DocCommentTester {
|
||||
* @return the normalized content
|
||||
*/
|
||||
String normalize(String s, boolean normalizeTags) {
|
||||
String s2 = s.trim().replaceFirst("\\.\\s*\\n *@", ".\n@");
|
||||
String s2 = s.trim().replaceFirst("\\.\\s*\\n *@(?![@*])", ".\n@");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Pattern p = Pattern.compile("(?i)\\{@([a-z][a-z0-9.:-]*)( )?");
|
||||
Matcher m = p.matcher(s2);
|
||||
@ -952,7 +957,7 @@ public class DocCommentTester {
|
||||
}
|
||||
|
||||
String normalizeFragment(String s) {
|
||||
return s.replaceAll("\n[ \t]+@", "\n@");
|
||||
return s.replaceAll("\n[ \t]+@(?![@*])", "\n@");
|
||||
}
|
||||
|
||||
int copyLiteral(String s, int start, StringBuilder sb) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user