mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
fix(JavaDoc-gen): compilation on backport, Better rendering, respect IDE options
Fixes IDEA-354610, IDEA-353932 Partially addresses IDEA-352642 fix(JavaDoc-format): handle indent on markdown fix(JavaDoc-backport): fix compilation GitOrigin-RevId: 5d1705da21be59ec0bc92a1b35bdf986a3227064
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0dc015188d
commit
2cfd03bd80
@@ -62,7 +62,6 @@ import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.xml.util.XmlStringUtil;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
@@ -1859,7 +1858,7 @@ public class JavaDocInfoGenerator {
|
||||
}
|
||||
else if (element instanceof PsiMarkdownCodeBlock markdownCodeBlock) {
|
||||
if (markdownCodeBlock.isInline()) {
|
||||
appendWrappedWithInlineCodeTag(subBuffer, markdownCodeBlock.getCodeText());
|
||||
appendStyledInlineCode(subBuffer, element.getProject(), markdownCodeBlock.getLanguage(), markdownCodeBlock.getCodeText());
|
||||
} else {
|
||||
appendStyledCodeBlock(subBuffer, element.getProject(), markdownCodeBlock.getCodeLanguage(), markdownCodeBlock.getCodeText());
|
||||
}
|
||||
@@ -1927,7 +1926,9 @@ public class JavaDocInfoGenerator {
|
||||
appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(
|
||||
doHighlightCodeBlocks(), buffer, myProject, JavaLanguage.INSTANCE,
|
||||
StringUtil.unescapeXmlEntities(StringUtil.replaceUnicodeEscapeSequences(htmlCodeBlockContents.toString()))
|
||||
.replace(" ", " "));
|
||||
.replace(" ", " ")
|
||||
.replace("@", "@")
|
||||
);
|
||||
buffer.append(CODE_BLOCK_SUFFIX);
|
||||
appendPlainText(buffer, text.substring(suffixIndex + delimiters.second.length()));
|
||||
return null;
|
||||
@@ -2241,26 +2242,15 @@ public class JavaDocInfoGenerator {
|
||||
|
||||
private static boolean isCodeBlock(PsiInlineDocTag tag) {
|
||||
if (!CODE_TAG.equals(tag.getName())) return false;
|
||||
|
||||
ASTNode prevNode = tag.getNode().getTreePrev();
|
||||
while (prevNode != null) {
|
||||
String text = prevNode.getText();
|
||||
if (prevNode.getElementType() == JavaDocTokenType.DOC_COMMENT_DATA) {
|
||||
if (StringUtil.endsWithIgnoreCase(StringUtil.trim(text), "<pre>")) {
|
||||
return true;
|
||||
}
|
||||
if (StringUtil.startsWithIgnoreCase(StringUtil.trim(text), "</pre>")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
prevNode = prevNode.getTreePrev();
|
||||
}
|
||||
return false;
|
||||
return isInPre(tag);
|
||||
}
|
||||
|
||||
private void generateCodeValue(PsiInlineDocTag tag, StringBuilder buffer) {
|
||||
boolean isCodeBlock = isCodeBlock(tag);
|
||||
|
||||
StringBuilder codeSnippetBuilder = new StringBuilder();
|
||||
generateLiteralValue(codeSnippetBuilder, tag, false);
|
||||
|
||||
if (isCodeBlock) {
|
||||
// remove excess whitespaces between tags e.g. in `<pre> {@code`
|
||||
int lastNonWhite = buffer.length() - 1;
|
||||
@@ -2268,37 +2258,11 @@ public class JavaDocInfoGenerator {
|
||||
buffer.setLength(lastNonWhite + 1);
|
||||
// Remove preceding <pre> fragment
|
||||
StringUtil.trimEnd(buffer, "<pre>");
|
||||
appendStyledCodeBlock(buffer, tag.getProject(), tag.getLanguage(), codeSnippetBuilder.toString());
|
||||
} else {
|
||||
String codeSnippet = codeSnippetBuilder.toString().replace("\n", "").trim();
|
||||
appendStyledInlineCode(buffer, tag.getProject(), tag.getLanguage(), codeSnippet);
|
||||
}
|
||||
|
||||
buffer.append(isCodeBlock ? CODE_BLOCK_PREFIX : INLINE_CODE_PREFIX);
|
||||
int pos = buffer.length();
|
||||
|
||||
StringBuilder codeSnippetBuilder = new StringBuilder();
|
||||
generateLiteralValue(codeSnippetBuilder, tag, false);
|
||||
String codeSnippet = codeSnippetBuilder.toString();
|
||||
if (isCodeBlock) {
|
||||
codeSnippet = StringsKt.trimIndent(codeSnippet);
|
||||
}
|
||||
|
||||
if (isCodeBlock && doHighlightCodeBlocks()
|
||||
|| !isCodeBlock && getInlineCodeHighlightingMode() == InlineCodeHighlightingMode.SEMANTIC_HIGHLIGHTING) {
|
||||
// highlights code by lexer
|
||||
codeSnippetBuilder.setLength(0);
|
||||
appendHighlightedByLexerAndEncodedAsHtmlCodeSnippet(true, codeSnippetBuilder, tag.getProject(), tag.getLanguage(), codeSnippet);
|
||||
codeSnippet = codeSnippetBuilder.toString();
|
||||
}
|
||||
else {
|
||||
codeSnippet = XmlStringUtil.escapeString(codeSnippet);
|
||||
}
|
||||
|
||||
if (!isCodeBlock) {
|
||||
// we are in inline @code block, we should remove all new lines
|
||||
codeSnippet = codeSnippet.replace(BR_TAG, "");
|
||||
}
|
||||
|
||||
buffer.append(codeSnippet);
|
||||
buffer.append(isCodeBlock ? CODE_BLOCK_SUFFIX : INLINE_CODE_SUFFIX);
|
||||
if (buffer.charAt(pos) == '\n') buffer.insert(pos, ' '); // line break immediately after opening tag is ignored by JEditorPane
|
||||
}
|
||||
|
||||
private void generateLiteralValue(StringBuilder buffer, PsiDocTag tag, boolean doEscaping) {
|
||||
@@ -2322,8 +2286,8 @@ public class JavaDocInfoGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInPre(PsiDocTag tag) {
|
||||
PsiElement sibling = tag.getPrevSibling();
|
||||
private static boolean isInPre(PsiElement element) {
|
||||
PsiElement sibling = element.getPrevSibling();
|
||||
while (sibling != null) {
|
||||
if (sibling instanceof PsiDocToken) {
|
||||
String text = StringUtil.toLowerCase(sibling.getText());
|
||||
|
||||
@@ -46,6 +46,25 @@ public class JDParser {
|
||||
private static final Pattern PRE_TAG_START_PATTERN = Pattern.compile(PRE_TAG_START_REGEXP);
|
||||
private static final Pattern SNIPPET_START_PATTERN = Pattern.compile(SNIPPET_START_REGEXP);
|
||||
|
||||
// Markdown tokens
|
||||
private static final String CODE_FENCE_BACKTICK = "```";
|
||||
private static final String CODE_FENCE_TILDE = "~~~";
|
||||
private static final String CODE_FENCE_BACKTICK_REGEXP = "`{3,}";
|
||||
private static final String CODE_FENCE_TILDE_REGEXP = "~{3,}";
|
||||
private static final Pattern CODE_FENCE_TILDE_PATTERN = Pattern.compile(CODE_FENCE_TILDE_REGEXP);
|
||||
private static final Pattern CODE_FENCE_BACKTICK_PATTERN = Pattern.compile(CODE_FENCE_BACKTICK_REGEXP);
|
||||
|
||||
private static final String LIST_ITEM_REGEXP = "^\\d+?[).]";
|
||||
private static final Pattern LIST_ITEM_PATTERN = Pattern.compile(LIST_ITEM_REGEXP);
|
||||
|
||||
private static final String LIST_ITEM_START = "- ";
|
||||
private static final String LIST_ITEM_START_2 = "+ ";
|
||||
private static final String LIST_ITEM_START_3 = "* ";
|
||||
private static final String LINE_SEPARATOR = "---";
|
||||
private static final String HEADER_START = "#";
|
||||
private static final String BLOCKQUOTE_START = ">";
|
||||
private static final String TABLE_ROW_START = "|";
|
||||
|
||||
private static final String[] TAGS_TO_KEEP_INDENTS_AFTER = {"table", "ol", "ul", "div", "dl"};
|
||||
|
||||
public JDParser(@NotNull CodeStyleSettings settings) {
|
||||
@@ -184,7 +203,7 @@ public class JDParser {
|
||||
// Note: Markdown comments are not trimmed like html ones, except for javadoc tags
|
||||
String newLine;
|
||||
int tagStart = CharArrayUtil.shiftForward(line, 3, " \t");
|
||||
if (tagStart != line.length()) {
|
||||
if (tagStart != line.length() && line.charAt(tagStart) == '@') {
|
||||
newLine = line.substring(tagStart);
|
||||
} else {
|
||||
newLine = StringUtil.trimStart(line, "/// ");
|
||||
@@ -259,17 +278,17 @@ public class JDParser {
|
||||
/**
|
||||
* Breaks the specified string by the specified separators into array of strings
|
||||
*
|
||||
* @param s the specified string
|
||||
* @param markers if this parameter is not null then it will be filled with Boolean values:
|
||||
* true if the corresponding line in returned list is inside <pre> tag,
|
||||
* false if it is outside
|
||||
* @param s the specified string
|
||||
* @param markers if this parameter is not null then it will be filled with Boolean values:
|
||||
* true if the corresponding line in returned list is inside <pre> tag or a markdown codeblock,
|
||||
* false if it is outside
|
||||
* @return list of strings (lines)
|
||||
*/
|
||||
private @Nullable List<String> toArray(@Nullable String s, @Nullable List<Boolean> markers, boolean markdownComment) {
|
||||
if (s == null) return null;
|
||||
s = s.trim();
|
||||
s = markdownComment ? s : s.trim();
|
||||
if (s.isEmpty()) return null;
|
||||
boolean p2nl = markers != null && mySettings.JD_P_AT_EMPTY_LINES;
|
||||
boolean p2nl = markers != null && mySettings.JD_P_AT_EMPTY_LINES && !markdownComment;
|
||||
List<String> list = new ArrayList<>();
|
||||
StringTokenizer st = new StringTokenizer(s, "\n", true);
|
||||
boolean first = true;
|
||||
@@ -280,6 +299,7 @@ public class JDParser {
|
||||
boolean isInMultilineTodo = false;
|
||||
boolean isInSnippet = false;
|
||||
int snippetBraceBalance = 0;
|
||||
String codeblockType = null;
|
||||
|
||||
while (st.hasMoreTokens()) {
|
||||
String token = st.nextToken();
|
||||
@@ -330,8 +350,25 @@ public class JDParser {
|
||||
snippetBraceBalance += getLineSnippetTagBraceBalance(token);
|
||||
}
|
||||
if (lineHasUnclosedPreTag(token)) preCount++;
|
||||
markers.add(preCount > 0 || firstLineToKeepIndents >= 0 || isInMultilineTodo || snippetBraceBalance != 0);
|
||||
if (markdownComment && codeblockType == null) {
|
||||
codeblockType = lineGetStartCodeFence(token);
|
||||
if (codeblockType != null) preCount++;
|
||||
}
|
||||
|
||||
markers.add(preCount > 0
|
||||
|| firstLineToKeepIndents >= 0
|
||||
|| isInMultilineTodo
|
||||
|| snippetBraceBalance != 0
|
||||
|| (markdownComment && isStartOfMarkdownHeader(token)) /* Markdown titles cannot be split */);
|
||||
|
||||
if (lineHasClosingPreTag(token)) preCount--;
|
||||
if (markdownComment && codeblockType != null) {
|
||||
if (Strings.areSameInstance(codeblockType, CODE_FENCE_BACKTICK) && token.contains(CODE_FENCE_BACKTICK)
|
||||
|| Strings.areSameInstance(codeblockType, CODE_FENCE_TILDE) && token.contains(CODE_FENCE_TILDE)) {
|
||||
preCount--;
|
||||
codeblockType = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -446,7 +483,7 @@ public class JDParser {
|
||||
while (true) {
|
||||
if (seq.length() < width || isMarked) {
|
||||
// keep remaining line and proceed with next paragraph
|
||||
seq = isMarked ? seq : seq.trim();
|
||||
seq = isMarked || markdownComment ? seq : seq.trim();
|
||||
list.add(seq);
|
||||
break;
|
||||
}
|
||||
@@ -542,7 +579,7 @@ public class JDParser {
|
||||
@Contract("null, _ -> null")
|
||||
private List<Pair<String, Boolean>> splitToParagraphs(@Nullable String s, boolean markdownComment) {
|
||||
if (s == null) return null;
|
||||
s = s.trim();
|
||||
s = markdownComment ? s : s.trim();
|
||||
if (s.isEmpty()) return null;
|
||||
|
||||
List<Pair<String, Boolean>> result = new ArrayList<>();
|
||||
@@ -556,10 +593,7 @@ public class JDParser {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
String s1 = list.get(i);
|
||||
if (marks[i].booleanValue()) {
|
||||
if (sb.length() != 0) {
|
||||
result.add(new Pair<>(sb.toString(), false));
|
||||
sb.setLength(0);
|
||||
}
|
||||
endParagraph(result, sb);
|
||||
result.add(Pair.create(s1, marks[i]));
|
||||
}
|
||||
else {
|
||||
@@ -568,8 +602,18 @@ public class JDParser {
|
||||
result.add(Pair.create(s1, marks[i]));
|
||||
}
|
||||
else {
|
||||
if (isStartOfMarkdownConstruct(s1)) {
|
||||
endParagraph(result, sb);
|
||||
}
|
||||
|
||||
if (sb.length() != 0) sb.append(' ');
|
||||
sb.append(s1);
|
||||
if (markdownComment && !sb.isEmpty()) {
|
||||
// When fusing lines together, horizontal spacing loses its meaning
|
||||
sb.append(s1.trim());
|
||||
}
|
||||
else {
|
||||
sb.append(s1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -583,6 +627,34 @@ public class JDParser {
|
||||
return mySettings.JD_PRESERVE_LINE_FEEDS || HtmlUtil.startsWithTag(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether there is a star of a markdown construct
|
||||
* That should not be merged into a single paragraph
|
||||
*/
|
||||
private static boolean isStartOfMarkdownConstruct(@NotNull String line) {
|
||||
String trimmedLine = line.trim();
|
||||
return trimmedLine.startsWith(BLOCKQUOTE_START)
|
||||
|| trimmedLine.startsWith(LINE_SEPARATOR)
|
||||
|| isStartOfMarkdownHeader(trimmedLine)
|
||||
|| isMarkdownTableRow(trimmedLine)
|
||||
|| isStartOfMarkdownListItem(trimmedLine);
|
||||
}
|
||||
|
||||
private static boolean isStartOfMarkdownHeader(@NotNull String line) {
|
||||
return line.trim().startsWith(HEADER_START);
|
||||
}
|
||||
|
||||
private static boolean isStartOfMarkdownListItem(@NotNull String line) {
|
||||
return line.startsWith(LIST_ITEM_START)
|
||||
|| line.startsWith(LIST_ITEM_START_2)
|
||||
|| line.startsWith(LIST_ITEM_START_3)
|
||||
|| LIST_ITEM_PATTERN.matcher(line).find();
|
||||
}
|
||||
|
||||
private static boolean isMarkdownTableRow(@NotNull String line) {
|
||||
return line.startsWith(TABLE_ROW_START) && StringUtil.getOccurrenceCount(line, TABLE_ROW_START) > 1;
|
||||
}
|
||||
|
||||
private static void endParagraph(@NotNull List<? super Pair<String, Boolean>> result, @NotNull StringBuilder sb) {
|
||||
if (sb.length() > 0) {
|
||||
result.add(new Pair<>(sb.toString(), false));
|
||||
@@ -720,6 +792,41 @@ public class JDParser {
|
||||
return StringUtil.getOccurrenceCount(line, PRE_TAG_END) > getOccurenceCount(line, PRE_TAG_START_PATTERN);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Detects a stating code block fence in a given line
|
||||
*
|
||||
* @return The code fence type, or null if none are found
|
||||
*/
|
||||
private static String lineGetStartCodeFence(@NotNull String line) {
|
||||
int backticks = getOccurenceCount(line, CODE_FENCE_BACKTICK_PATTERN);
|
||||
int tildes = getOccurenceCount(line, CODE_FENCE_TILDE_PATTERN);
|
||||
|
||||
boolean hasBacktickStart = backticks % 2 != 0;
|
||||
boolean hasTildeStart = tildes % 2 != 0;
|
||||
|
||||
if (hasBacktickStart && hasTildeStart) {
|
||||
if (backticks == tildes) {
|
||||
// find the first fence
|
||||
int backtickIndex = line.lastIndexOf(CODE_FENCE_BACKTICK);
|
||||
int tildeIndex = line.lastIndexOf(CODE_FENCE_TILDE);
|
||||
return backtickIndex > tildeIndex ? CODE_FENCE_TILDE : CODE_FENCE_BACKTICK;
|
||||
}
|
||||
else {
|
||||
// give back whoever has the least amount of occurrences
|
||||
return backticks > tildes ? CODE_FENCE_TILDE : CODE_FENCE_BACKTICK;
|
||||
}
|
||||
}
|
||||
else if (hasTildeStart) {
|
||||
return CODE_FENCE_BACKTICK;
|
||||
}
|
||||
else if (hasBacktickStart) {
|
||||
return CODE_FENCE_TILDE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
private static int getOccurenceCount(@NotNull String line, @NotNull Pattern pattern) {
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PsiMarkdownCodeBlockImpl extends CompositePsiElement implements Psi
|
||||
|
||||
@Override
|
||||
public boolean isInline() {
|
||||
return getFirstChildNode().getTokenType() == JavaDocTokenType.DOC_INLINE_CODE_FENCE;
|
||||
return getFirstChildNode().getElementType() == JavaDocTokenType.DOC_INLINE_CODE_FENCE;
|
||||
}
|
||||
|
||||
private @Nullable String getLanguageInfo() {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">Main</span></pre></div><div class='content'>
|
||||
<pre><code><span style="">@Service<br></span><span style="color:#000080;font-weight:bold;">public class </span><span style="">TestService {}</span></code></pre>
|
||||
</div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* <pre><code>
|
||||
* @Service
|
||||
* public class TestService {}
|
||||
* </code></pre>
|
||||
*/
|
||||
class Main {
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">InfoGen</span><span style=""><</span><span style="color:#20999d;">K</span><span style="">, </span><span style="color:#20999d;">V</span><span style="">></span></pre></div><div class='content'>
|
||||
Hash table based implementation of the <code><span style="">Map</span></code> interface. This
|
||||
implementation provides all of the optional map operations, and permits
|
||||
<code><span style="color:#000080;font-weight:bold;">null</span></code> values and the <code><span style="color:#000080;font-weight:bold;">null</span></code> key. (The <code><span style="">HashMap</span></code>
|
||||
class is roughly equivalent to <code><span style="">Hashtable</span></code>, except that it is
|
||||
unsynchronized and permits nulls.) This class makes no guarantees as to
|
||||
the order of the map; in particular, it does not guarantee that the order
|
||||
will remain constant over time.
|
||||
|
||||
<p>This implementation provides constant-time performance for the basic
|
||||
operations (<code><span style="">get</span></code> and <code><span style="">put</span></code>), assuming the hash function
|
||||
disperses the elements properly among the buckets. Iteration over
|
||||
collection views requires time proportional to the "capacity" of the
|
||||
<code><span style="">HashMap</span></code> instance (the number of buckets) plus its size (the number
|
||||
of key-value mappings). Thus, it's very important not to set the initial
|
||||
capacity too high (or the load factor too low) if iteration performance is
|
||||
important.
|
||||
|
||||
<p>An instance of <code><span style="">HashMap</span></code> has two parameters that affect its
|
||||
performance: <i>initial capacity</i> and <i>load factor</i>. The
|
||||
<i>capacity</i> is the number of buckets in the hash table, and the initial
|
||||
capacity is simply the capacity at the time the hash table is created. The
|
||||
<i>load factor</i> is a measure of how full the hash table is allowed to
|
||||
get before its capacity is automatically increased. When the number of
|
||||
entries in the hash table exceeds the product of the load factor and the
|
||||
current capacity, the hash table is <i>rehashed</i> (that is, internal data
|
||||
structures are rebuilt) so that the hash table has approximately twice the
|
||||
number of buckets.
|
||||
|
||||
<p>As a general rule, the default load factor (.75) offers a good
|
||||
tradeoff between time and space costs. Higher values decrease the
|
||||
space overhead but increase the lookup cost (reflected in most of
|
||||
the operations of the <code><span style="">HashMap</span></code> class, including
|
||||
<code><span style="">get</span></code> and <code><span style="">put</span></code>). The expected number of entries in
|
||||
the map and its load factor should be taken into account when
|
||||
setting its initial capacity, so as to minimize the number of
|
||||
rehash operations. If the initial capacity is greater than the
|
||||
maximum number of entries divided by the load factor, no rehash
|
||||
operations will ever occur.
|
||||
|
||||
<p>If many mappings are to be stored in a <code><span style="">HashMap</span></code>
|
||||
instance, creating it with a sufficiently large capacity will allow
|
||||
the mappings to be stored more efficiently than letting it perform
|
||||
automatic rehashing as needed to grow the table. Note that using
|
||||
many keys with the same <code><span style="">hashCode()</span></code> is a sure way to slow
|
||||
down performance of any hash table. To ameliorate impact, when keys
|
||||
are <a href="psi_element://java.lang.Comparable"><code><span style="color:#0000ff;">Comparable</span></code></a>, this class may use comparison order among
|
||||
keys to help break ties.
|
||||
|
||||
<p><strong>Note that this implementation is not synchronized.</strong>
|
||||
If multiple threads access a hash map concurrently, and at least one of
|
||||
the threads modifies the map structurally, it <i>must</i> be
|
||||
synchronized externally. (A structural modification is any operation
|
||||
that adds or deletes one or more mappings; merely changing the value
|
||||
associated with a key that an instance already contains is not a
|
||||
structural modification.) This is typically accomplished by
|
||||
synchronizing on some object that naturally encapsulates the map.
|
||||
|
||||
If no such object exists, the map should be "wrapped" using the
|
||||
<a href="psi_element://java.util.Collections#synchronizedMap(java.util.Map)"><code><span style="color:#0000ff;">Collections</span><span style="">.</span><span style="color:#0000ff;">synchronizedMap</span></code></a>
|
||||
method. This is best done at creation time, to prevent accidental
|
||||
unsynchronized access to the map:<pre>
|
||||
Map m = Collections.synchronizedMap(new HashMap(...));</pre>
|
||||
|
||||
<p>The iterators returned by all of this class's "collection view methods"
|
||||
are <i>fail-fast</i>: if the map is structurally modified at any time after
|
||||
the iterator is created, in any way except through the iterator's own
|
||||
<code><span style="">remove</span></code> method, the iterator will throw a
|
||||
<a href="psi_element://java.util.ConcurrentModificationException"><code><span style="color:#0000ff;">ConcurrentModificationException</span></code></a>. Thus, in the face of concurrent
|
||||
modification, the iterator fails quickly and cleanly, rather than risking
|
||||
arbitrary, non-deterministic behavior at an undetermined time in the
|
||||
future.
|
||||
|
||||
<p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
throw <code><span style="">ConcurrentModificationException</span></code> on a best-effort basis.
|
||||
Therefore, it would be wrong to write a program that depended on this
|
||||
exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
should be used only to detect bugs.</i>
|
||||
|
||||
<p>This class is a member of the
|
||||
<a href="/java.base/java/util/package-summary.html#CollectionsFramework">
|
||||
Java Collections Framework</a>.
|
||||
|
||||
</div><table class='sections'><p><tr><td valign='top' class='section'><p>Since:</td><td valign='top'><p> 1.2</td><tr><td valign='top' class='section'><p>See Also:</td><td valign='top'><p><a href="psi_element://java.lang.Object#hashCode()"><code><span style="color:#0000ff;">Object</span><span style="">.</span><span style="color:#0000ff;">hashCode</span><span style="">()</span></code></a>,<br><a href="psi_element://java.util.Collection"><code><span style="color:#0000ff;">Collection</span></code></a>,<br><a href="psi_element://java.util.Map"><code><span style="color:#0000ff;">Map</span></code></a>,<br><a href="psi_element://java.util.TreeMap"><code><span style="color:#0000ff;">TreeMap</span></code></a>,<br><a href="psi_element://java.util.Hashtable"><code><span style="color:#0000ff;">Hashtable</span></code></a></td><tr><td valign='top' class='section'><p>Author:</td><td valign='top'><p>Doug Lea, Josh Bloch, Arthur van Hoff, Neal Gafter</td><tr><td valign='top' class='section'><p>Type parameters:</td><td valign='top'><code><<span style="color:#20999d;">K</span>></code> – the type of keys maintained by this map <br><code><<span style="color:#20999d;">V</span>></code> – the type of mapped values </td></table>
|
||||
@@ -0,0 +1,104 @@
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Hash table based implementation of the {@code Map} interface. This
|
||||
* implementation provides all of the optional map operations, and permits
|
||||
* {@code null} values and the {@code null} key. (The {@code HashMap}
|
||||
* class is roughly equivalent to {@code Hashtable}, except that it is
|
||||
* unsynchronized and permits nulls.) This class makes no guarantees as to
|
||||
* the order of the map; in particular, it does not guarantee that the order
|
||||
* will remain constant over time.
|
||||
*
|
||||
* <p>This implementation provides constant-time performance for the basic
|
||||
* operations ({@code get} and {@code put}), assuming the hash function
|
||||
* disperses the elements properly among the buckets. Iteration over
|
||||
* collection views requires time proportional to the "capacity" of the
|
||||
* {@code HashMap} instance (the number of buckets) plus its size (the number
|
||||
* of key-value mappings). Thus, it's very important not to set the initial
|
||||
* capacity too high (or the load factor too low) if iteration performance is
|
||||
* important.
|
||||
*
|
||||
* <p>An instance of {@code HashMap} has two parameters that affect its
|
||||
* performance: <i>initial capacity</i> and <i>load factor</i>. The
|
||||
* <i>capacity</i> is the number of buckets in the hash table, and the initial
|
||||
* capacity is simply the capacity at the time the hash table is created. The
|
||||
* <i>load factor</i> is a measure of how full the hash table is allowed to
|
||||
* get before its capacity is automatically increased. When the number of
|
||||
* entries in the hash table exceeds the product of the load factor and the
|
||||
* current capacity, the hash table is <i>rehashed</i> (that is, internal data
|
||||
* structures are rebuilt) so that the hash table has approximately twice the
|
||||
* number of buckets.
|
||||
*
|
||||
* <p>As a general rule, the default load factor (.75) offers a good
|
||||
* tradeoff between time and space costs. Higher values decrease the
|
||||
* space overhead but increase the lookup cost (reflected in most of
|
||||
* the operations of the {@code HashMap} class, including
|
||||
* {@code get} and {@code put}). The expected number of entries in
|
||||
* the map and its load factor should be taken into account when
|
||||
* setting its initial capacity, so as to minimize the number of
|
||||
* rehash operations. If the initial capacity is greater than the
|
||||
* maximum number of entries divided by the load factor, no rehash
|
||||
* operations will ever occur.
|
||||
*
|
||||
* <p>If many mappings are to be stored in a {@code HashMap}
|
||||
* instance, creating it with a sufficiently large capacity will allow
|
||||
* the mappings to be stored more efficiently than letting it perform
|
||||
* automatic rehashing as needed to grow the table. Note that using
|
||||
* many keys with the same {@code hashCode()} is a sure way to slow
|
||||
* down performance of any hash table. To ameliorate impact, when keys
|
||||
* are {@link Comparable}, this class may use comparison order among
|
||||
* keys to help break ties.
|
||||
*
|
||||
* <p><strong>Note that this implementation is not synchronized.</strong>
|
||||
* If multiple threads access a hash map concurrently, and at least one of
|
||||
* the threads modifies the map structurally, it <i>must</i> be
|
||||
* synchronized externally. (A structural modification is any operation
|
||||
* that adds or deletes one or more mappings; merely changing the value
|
||||
* associated with a key that an instance already contains is not a
|
||||
* structural modification.) This is typically accomplished by
|
||||
* synchronizing on some object that naturally encapsulates the map.
|
||||
*
|
||||
* If no such object exists, the map should be "wrapped" using the
|
||||
* {@link Collections#synchronizedMap Collections.synchronizedMap}
|
||||
* method. This is best done at creation time, to prevent accidental
|
||||
* unsynchronized access to the map:<pre>
|
||||
* Map m = Collections.synchronizedMap(new HashMap(...));</pre>
|
||||
*
|
||||
* <p>The iterators returned by all of this class's "collection view methods"
|
||||
* are <i>fail-fast</i>: if the map is structurally modified at any time after
|
||||
* the iterator is created, in any way except through the iterator's own
|
||||
* {@code remove} method, the iterator will throw a
|
||||
* {@link ConcurrentModificationException}. Thus, in the face of concurrent
|
||||
* modification, the iterator fails quickly and cleanly, rather than risking
|
||||
* arbitrary, non-deterministic behavior at an undetermined time in the
|
||||
* future.
|
||||
*
|
||||
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
|
||||
* as it is, generally speaking, impossible to make any hard guarantees in the
|
||||
* presence of unsynchronized concurrent modification. Fail-fast iterators
|
||||
* throw {@code ConcurrentModificationException} on a best-effort basis.
|
||||
* Therefore, it would be wrong to write a program that depended on this
|
||||
* exception for its correctness: <i>the fail-fast behavior of iterators
|
||||
* should be used only to detect bugs.</i>
|
||||
*
|
||||
* <p>This class is a member of the
|
||||
* <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
|
||||
* Java Collections Framework</a>.
|
||||
*
|
||||
* @param <K> the type of keys maintained by this map
|
||||
* @param <V> the type of mapped values
|
||||
*
|
||||
* @author Doug Lea
|
||||
* @author Josh Bloch
|
||||
* @author Arthur van Hoff
|
||||
* @author Neal Gafter
|
||||
* @see Object#hashCode()
|
||||
* @see Collection
|
||||
* @see Map
|
||||
* @see TreeMap
|
||||
* @see Hashtable
|
||||
* @since 1.2
|
||||
*/
|
||||
class InfoGen<K, V> {
|
||||
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownFeatures</span></pre></div><div class='content'><h1>Title1</h1><h2>Title2</h2><h3>Title 3</h3><p><em>italic</em> <strong>strong</strong> <code>code</code></p><p>Separate paragraph</p> <pre><code><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello there"</span><span style="">);</span></code></pre>
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownFeatures</span></pre></div><div class='content'><h1>Title1</h1><h2>Title2</h2><h3>Title 3</h3><p><em>italic</em> <strong>strong</strong> <code><span style="">code</span></code></p><p>Separate paragraph</p> <pre><code><span style="">System.out.println(</span><span style="color:#008000;font-weight:bold;">"Hello there"</span><span style="">);</span></code></pre>
|
||||
</div><table class='sections'><p></table>
|
||||
@@ -1,3 +1,3 @@
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">MarkdownCodeBlock</span></pre></div><div class='content'><p>Single liner code block:
|
||||
<code>Hello world</code></p><p>No tags are interpreted inside them
|
||||
<code>{@link java.lang.String niceLink}</code></p></div><table class='sections'><p></table>
|
||||
<code><span style="">Hello world</span></code></p><p>No tags are interpreted inside them
|
||||
<code><span style="">{@link java.lang.String niceLink}</span></code></p></div><table class='sections'><p></table>
|
||||
@@ -1 +1 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://InlineWithTagsMarkdown"><code><span style="color:#000000;">InlineWithTagsMarkdown</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">boolean</span> <span style="color:#000000;">foo</span><span style="">(</span><br> <span style="color:#000080;font-weight:bold;">int</span> <span style="color:#000000;">bar</span><br><span style="">)</span></pre></div><table class='sections'><p><tr><td valign='top' class='section'><p>Params:</td><td valign='top'><code><span style="color:#000000;">bar</span></code> – an int, set to <code>-1</code></td><tr><td valign='top' class='section'><p>Returns:</td><td valign='top'><p><em>Some value</em></td></table>
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://InlineWithTagsMarkdown"><code><span style="color:#000000;">InlineWithTagsMarkdown</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">boolean</span> <span style="color:#000000;">foo</span><span style="">(</span><br> <span style="color:#000080;font-weight:bold;">int</span> <span style="color:#000000;">bar</span><br><span style="">)</span></pre></div><table class='sections'><p><tr><td valign='top' class='section'><p>Params:</td><td valign='top'><code><span style="color:#000000;">bar</span></code> – an int, set to <code><span style="">-</span><span style="color:#0000ff;">1</span></code></td><tr><td valign='top' class='section'><p>Returns:</td><td valign='top'><p><em>Some value</em></td></table>
|
||||
@@ -1,17 +1,17 @@
|
||||
<html><head><base href="placeholder"></head><body><div class="bottom"><icon src="AllIcons.Nodes.Class"> <a href="psi_element://MarkdownJepExample"><code><span style="color:#000000;">MarkdownJepExample</span></code></a></div><div class='definition'><pre><span style="color:#000080;font-weight:bold;">public</span> <a href="psi_element://java.lang.String"><code><span style="color:#000000;">String</span></code></a> <span style="color:#000000;">longExample</span><span style="">(</span><span style="">)</span></pre></div><div class='content'><p>Returns a hash code value for the object. This method is
|
||||
supported for the benefit of hash tables such as those provided by
|
||||
<a href="psi_element://java.util.HashMap"><code><span style="color:#0000ff;">java.util.HashMap</span></code></a>.</p><p>The general contract of <code>hashCode</code> is:</p><ul><li>Whenever it is invoked on the same object more than once during
|
||||
an execution of a Java application, the <code>hashCode</code> method
|
||||
<a href="psi_element://java.util.HashMap"><code><span style="color:#0000ff;">java.util.HashMap</span></code></a>.</p><p>The general contract of <code><span style="">hashCode</span></code> is:</p><ul><li>Whenever it is invoked on the same object more than once during
|
||||
an execution of a Java application, the <code><span style="">hashCode</span></code> method
|
||||
must consistently return the same integer, provided no information
|
||||
used in <code>equals</code> comparisons on the object is modified.
|
||||
used in <code><span style="">equals</span></code> comparisons on the object is modified.
|
||||
This integer need not remain consistent from one execution of an
|
||||
application to another execution of the same application.</li><li>If two objects are equal according to the
|
||||
<a href="psi_element://java.lang.Object#equals(java.lang.Object)"><span style="color:#0000ff;">equals</span></a> method, then calling the
|
||||
<code>hashCode</code> method on each of the two objects must produce the
|
||||
<code><span style="">hashCode</span></code> method on each of the two objects must produce the
|
||||
same integer result.</li><li>It is <em>not</em> required that if two objects are unequal
|
||||
according to the <a href="psi_element://java.lang.Object#equals(java.lang.Object)"><span style="color:#0000ff;">equals</span></a> method, then
|
||||
calling the <code>hashCode</code> method on each of the two objects
|
||||
calling the <code><span style="">hashCode</span></code> method on each of the two objects
|
||||
must produce distinct integer results. However, the programmer
|
||||
should be aware that producing distinct integer results for
|
||||
unequal objects may improve the performance of hash tables.</li></ul></div><table class='sections'><tr><td valign='top' class='section'><p>Returns:</td><td valign='top'><p>a hash code value for this object.</td><tr><td valign='top' class='section'><p>Implementation<br>Requirements:</td><td valign='top'><p><p>As far as is reasonably practical, the <code>hashCode</code> method defined
|
||||
by class <code>Object</code> returns distinct integers for distinct objects.</p></td><tr><td valign='top' class='section'><p>See Also:</td><td valign='top'><p><a href="psi_element://java.lang.Object#equals(java.lang.Object)"><code><span style="color:#0000ff;">Object</span><span style="">.</span><span style="color:#0000ff;">equals</span><span style="">(Object)</span></code></a>,<br><a href="psi_element://java.lang.System#identityHashCode(java.lang.Object)"><code><span style="color:#0000ff;">System</span><span style="">.</span><span style="color:#0000ff;">identityHashCode</span></code></a></td></table>
|
||||
unequal objects may improve the performance of hash tables.</li></ul></div><table class='sections'><tr><td valign='top' class='section'><p>Returns:</td><td valign='top'><p>a hash code value for this object.</td><tr><td valign='top' class='section'><p>Implementation<br>Requirements:</td><td valign='top'><p><p>As far as is reasonably practical, the <code><span style="">hashCode</span></code> method defined
|
||||
by class <code><span style="">Object</span></code> returns distinct integers for distinct objects.</p></td><tr><td valign='top' class='section'><p>See Also:</td><td valign='top'><p><a href="psi_element://java.lang.Object#equals(java.lang.Object)"><code><span style="color:#0000ff;">Object</span><span style="">.</span><span style="color:#0000ff;">equals</span><span style="">(Object)</span></code></a>,<br><a href="psi_element://java.lang.System#identityHashCode(java.lang.Object)"><code><span style="color:#0000ff;">System</span><span style="">.</span><span style="color:#0000ff;">identityHashCode</span></code></a></td></table>
|
||||
@@ -0,0 +1,6 @@
|
||||
<html><head><base href="placeholder"></head><body><div class='definition'><pre><span style="color:#000080;font-weight:bold;">class</span> <span style="color:#000000;">Test</span></pre></div><div class='content'>
|
||||
<pre>
|
||||
Beautiful pre content, inline with one of the tags. This somehow trips dectection for the @code tag.
|
||||
So now we have a test. But god forbid you put a space at the closing tag.</pre>
|
||||
<code><span style="">-</span><span style="color:#0000ff;">1</span></code> text inline with the @code tag ?
|
||||
</div><table class='sections'><p></table>
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* <pre>
|
||||
* Beautiful pre content, inline with one of the tags. This somehow trips dectection for the @code tag.
|
||||
* So now we have a test. But god forbid you put a space at the closing tag.</pre>
|
||||
* {@code -1} text inline with the @code tag ?
|
||||
*/
|
||||
class Test {
|
||||
public String field = null;
|
||||
}
|
||||
@@ -205,6 +205,16 @@ public class JavaDocInfoGeneratorTest extends JavaCodeInsightTestCase {
|
||||
}
|
||||
public void testMarkdownInlineCodeBlock() { doTestClass(); }
|
||||
|
||||
public void testHashMapCodeTags() {
|
||||
doTestClass();
|
||||
}
|
||||
public void testEscapeHtmlCodesInCodeBlock(){
|
||||
doTestClass();
|
||||
}
|
||||
public void testPreTagLeakBeforeCode() {
|
||||
doTestClass();
|
||||
}
|
||||
|
||||
|
||||
public void testRepeatableAnnotations() {
|
||||
useJava8();
|
||||
|
||||
@@ -1871,7 +1871,7 @@ public class Test {
|
||||
/// Purposefully misaaligned stuff
|
||||
public class Main {}
|
||||
""".trimIndent(), """
|
||||
/// Purposefully misaaligned stuff
|
||||
/// Purposefully misaaligned stuff
|
||||
public class Main {
|
||||
}
|
||||
""".trimIndent())
|
||||
@@ -1947,4 +1947,88 @@ public class Test {
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun testListItemIndentBeingPreserved() {
|
||||
settings.apply {
|
||||
WRAP_COMMENTS = true
|
||||
RIGHT_MARGIN = 120
|
||||
}
|
||||
javaSettings.apply {
|
||||
JD_PRESERVE_LINE_FEEDS = false
|
||||
}
|
||||
|
||||
doTextTest("""
|
||||
/// This method is
|
||||
/// supported for the benefit of hash tables such as those provided by
|
||||
/// [java.util.HashMap].
|
||||
///
|
||||
/// The general contract of `hashCode` is:
|
||||
///
|
||||
/// - Whenever it is invoked on the same object more than once during
|
||||
/// an execution of a Java application, the `hashCode` method abusively long line that will force the line feed to be cut nonetheless, what will you do in the situation
|
||||
/// This integer need not remain consistent from one execution of an
|
||||
/// application to another execution of the same application.
|
||||
/// + If two objects are equal according to the
|
||||
/// [equals][#equals(Object)] method
|
||||
/// * It is _not_ required that if two objects are unequal
|
||||
/// according to the [equals][#equals(Object)] method
|
||||
///
|
||||
/// @param toto As a tag, it should be brought back to the left
|
||||
class C {}
|
||||
""".trimIndent(), """
|
||||
/// This method is supported for the benefit of hash tables such as those provided by [java.util.HashMap].
|
||||
///
|
||||
/// The general contract of `hashCode` is:
|
||||
///
|
||||
/// - Whenever it is invoked on the same object more than once during an execution of a Java application, the
|
||||
/// `hashCode` method abusively long line that will force the line feed to be cut nonetheless, what will you do in the
|
||||
/// situation This integer need not remain consistent from one execution of an application to another execution of the
|
||||
/// same application.
|
||||
/// + If two objects are equal according to the [equals][#equals(Object)] method
|
||||
/// * It is _not_ required that if two objects are unequal according to the [equals][#equals(Object)] method
|
||||
///
|
||||
/// @param toto As a tag, it should be brought back to the left
|
||||
class C {
|
||||
}
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
fun testMarkdownConstructsImmuneToWrapping() {
|
||||
settings.apply {
|
||||
WRAP_COMMENTS = true
|
||||
RIGHT_MARGIN = 120
|
||||
}
|
||||
javaSettings.apply {
|
||||
JD_PRESERVE_LINE_FEEDS = false
|
||||
}
|
||||
|
||||
doTextTest("""
|
||||
/// | Latin | Greek |
|
||||
/// |-------|-------|
|
||||
/// | a | alpha |
|
||||
/// | b | beta |
|
||||
/// | c | gamma |
|
||||
///
|
||||
/// > Nice blockquote
|
||||
/// - Single list item
|
||||
/// + Sub element
|
||||
/// * Another sub element
|
||||
/// ---
|
||||
/// # Title, but I have a long text, so loong in fact that it will probably get wrapped. Depends on whether I wrote my code properly. Anyhow, is someone down for a game of Minecraft ?
|
||||
///
|
||||
""".trimIndent(), """
|
||||
/// | Latin | Greek |
|
||||
/// |-------|-------|
|
||||
/// | a | alpha |
|
||||
/// | b | beta |
|
||||
/// | c | gamma |
|
||||
///
|
||||
/// > Nice blockquote
|
||||
/// - Single list item
|
||||
/// + Sub element
|
||||
/// * Another sub element
|
||||
/// ---
|
||||
/// # Title, but I have a long text, so loong in fact that it will probably get wrapped. Depends on whether I wrote my code properly. Anyhow, is someone down for a game of Minecraft ?
|
||||
""".trimIndent())
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,7 @@ new Gr<caret>oovyDocTest<Integer>()""", """\
|
||||
def foo() {}
|
||||
fo<caret>o()
|
||||
""", "<div class=\"bottom\"><icon src=\"AllIcons.Nodes.Class\"> <a href=\"psi_element://_\"><code><span style=\"color:#000000;\">_</span></code></a></div><div class='definition'><pre><a href=\"psi_element://java.lang.Object\"><code><span style=\"color:#000000;\">Object</span></code></a> <span style=\"color:#000000;\">foo</span><span style=\"\">(</span><span style=\"\">)</span></pre></div><div class='content'>\n" +
|
||||
" <code><span style=\"\">aaa</span><span style=\"\"> bbb</span><span style=\"\"> ccc</span></code>\n" +
|
||||
" <code><span style=\"\">aaa bbb ccc</span></code>\n" +
|
||||
" </div><table class='sections'></table>"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user