From interface: | java.util.Collection
+throws IOException
From interface: | java.util.Collection
Returns true if this collection contains the specified element.
More formally, returns true if and only if this collection
contains at least one element e such that
- (o==null ? e==null : o.equals(e)).
+ (o==null ? e==null : o.equals(e)).
| Overrides: | contains in interface Collection
contains in interface I
| Params: | o – element whose presence in this collection is to be tested | Returns: | true if this collection contains the specified element | Throws: | NullPointerException – before if the specified element is null and this collection does not permit null elements (optional) after
IOException |
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html b/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html
index a242f4599409..8ca4c07c71e4 100644
--- a/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html
+++ b/java/java-tests/testData/codeInsight/javadocIG/dumbMode.html
@@ -1,4 +1,4 @@
\ No newline at end of file
+
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html
index 317b5b0278cd..187473cec99f 100644
--- a/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html
+++ b/java/java-tests/testData/codeInsight/javadocIG/packageInfoWithCopyright/packageInfo.html
@@ -1,3 +1,3 @@
packageInfoWithCopyright
- This package contains nothing but package-info.java
+ This package contains nothing but package-info.java
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html b/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html
index e04069ccd330..e5cf83b6625f 100644
--- a/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html
+++ b/java/java-tests/testData/codeInsight/javadocIG/reflectConstructor.html
@@ -1,5 +1,5 @@
-@CallerSensitive
+ < java 10 >
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html b/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html
index 9d63edfa68eb..bab3a49a624e 100644
--- a/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html
+++ b/java/java-tests/testData/codeInsight/javadocIG/syntheticEnumValues.html
@@ -4,8 +4,8 @@
type, in the order they're declared. This method may be
used to iterate over the constants as follows:
- for(E c : E.values())
- System.out.println(c);
+ for(E c : E.values())
+ System.out.println(c);
Returns: | an array containing the constants of this enum type, in the order they're declared |
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt
index 09d548394b9a..62920f7bb498 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JavaDocumentationTest.kt
@@ -289,7 +289,7 @@ class JavaDocumentationTest : LightJavaCodeInsightFixtureTestCase() {
val actual = JavaExternalDocumentationTest.getDocumentationText(myFixture.project, input)
- val expected = "Candidates for method call s.regionMatches() are: " +
+ val expected = " Candidates for method call s.regionMatches() are: " +
" " +
" boolean regionMatches(int, String, int, int)" +
" boolean regionMatches(boolean, int, String, int, int)" +
@@ -309,7 +309,7 @@ class JavaDocumentationTest : LightJavaCodeInsightFixtureTestCase() {
val documentationManager = DocumentationManager.getInstance(myFixture.project)
JavaExternalDocumentationTest.getDocumentationText(myFixture.project, input) { component ->
- val expected = " Candidates for method call s.regionMatches() are: " +
+ val expected = " Candidates for method call s.regionMatches() are: " +
" " +
" boolean regionMatches(int, String, int, int)" +
" boolean regionMatches(boolean, int, String, int, int)" +
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java
index 52c8b1b0c4df..7ee7d364de0c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationEditorPane.java
@@ -81,10 +81,11 @@ public abstract class DocumentationEditorPane extends JEditorPane implements Dis
}
setBackground(BACKGROUND_COLOR);
HTMLEditorKit editorKit = new HTMLEditorKitBuilder()
- .replaceViewFactoryExtensions(DocumentationHtmlUtil.getIconsExtension(iconResolver),
+ .replaceViewFactoryExtensions(getIconsExtension(iconResolver),
Extensions.BASE64_IMAGES,
Extensions.INLINE_VIEW_EX,
- Extensions.FIT_TO_WIDTH_IMAGES)
+ Extensions.FIT_TO_WIDTH_IMAGES,
+ Extensions.WBR_SUPPORT)
.withFontResolver(EditorCssFontResolver.getGlobalInstance()).build();
updateDocumentationPaneDefaultCssRules(editorKit);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt
index 12c6356be314..d51b1c23a833 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationHtmlUtil.kt
@@ -16,6 +16,7 @@ import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import org.intellij.lang.annotations.Language
import org.jetbrains.annotations.ApiStatus
+import org.jetbrains.annotations.Contract
import java.awt.Color
import java.util.function.Function
import javax.swing.Icon
@@ -79,6 +80,7 @@ object DocumentationHtmlUtil {
val contentSpacing = scale(contentSpacing)
val contentInnerPadding = scale(contentInnerPadding)
+ @Suppress("CssUnusedSymbol")
@Language("CSS")
val result = ContainerUtil.newLinkedList(
"""
@@ -116,4 +118,115 @@ object DocumentationHtmlUtil {
result.addAll(getDefaultFormattingStyles(contentSpacing))
return result
}
+
+ @JvmStatic
+ @Contract(pure = true)
+ fun addWordBreaks(text: String): String {
+ val codePoints = text.codePoints().iterator()
+ if (!codePoints.hasNext()) return ""
+ val result = StringBuilder(text.length + 50)
+ var codePoint = codePoints.nextInt()
+ val tagName = StringBuilder()
+
+ fun next(builder: StringBuilder = result) {
+ builder.appendCodePoint(codePoint)
+ codePoint = if (codePoints.hasNext())
+ codePoints.nextInt()
+ else
+ -1
+ }
+
+ while (codePoint >= 0) {
+ // break after dot if surrounded by letters
+ when {
+ Character.isLetter(codePoint) -> {
+ next()
+ if (codePoint == '.'.code) {
+ next()
+ if (Character.isLetter(codePoint)) {
+ result.append(" ")
+ }
+ }
+ }
+ // break after ], ) or / followed by a char or digit
+ codePoint == ')'.code || codePoint == ']'.code || codePoint == '/'.code -> {
+ next()
+ if (Character.isLetterOrDigit(codePoint)) {
+ result.append("")
+ }
+ }
+ // skip tag
+ codePoint == '<'.code -> {
+ next()
+ if (codePoint == '/'.code)
+ next()
+ if (!Character.isLetter(codePoint))
+ continue
+ tagName.clear()
+ while (Character.isLetterOrDigit(codePoint) || codePoint == '-'.code) {
+ next(tagName)
+ }
+ result.append(tagName)
+ if (tagName.contentEquals("style", true)
+ || tagName.contentEquals("title", true)
+ || tagName.contentEquals("script", true)) {
+ val curTag = tagName.toString()
+ do {
+ if (codePoint == '<'.code) {
+ next()
+ if (codePoint == '/'.code) {
+ next()
+ tagName.clear()
+ while (Character.isLetterOrDigit(codePoint) || codePoint == '-'.code) {
+ next(tagName)
+ }
+ result.append(tagName)
+ if (tagName.contentEquals(curTag, true)) {
+ while (codePoint >= 0 && codePoint != '>'.code) {
+ next()
+ }
+ break
+ }
+ }
+ }
+ else next()
+ }
+ while (true)
+ }
+ else {
+ while (codePoint >= 0) {
+ when (codePoint) {
+ '>'.code -> {
+ next()
+ break
+ }
+ '\''.code, '"'.code -> {
+ val quoteStyle = codePoint
+ next()
+ while (codePoint >= 0) {
+ when (codePoint) {
+ '\\'.code -> {
+ next()
+ if (codePoint >= 0)
+ next()
+ }
+ quoteStyle -> {
+ next()
+ break
+ }
+ else -> next()
+ }
+ }
+ }
+ else -> next()
+ }
+ }
+ }
+ }
+ else -> next()
+ }
+ }
+
+ return result.toString()
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index 3c69c3176825..b2343e2b40d0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -112,6 +112,7 @@ import static com.intellij.lang.documentation.DocumentationMarkup.*;
*
* @deprecated Unused in v2 implementation. Unsupported: use at own risk.
*/
+@SuppressWarnings("removal")
@Deprecated(forRemoval = true)
public class DocumentationManager extends DockablePopupManager {
public static final String JAVADOC_LOCATION_AND_SIZE = "javadoc.popup";
@@ -1942,6 +1943,7 @@ public class DocumentationManager extends DockablePopupManager" + text.substring(nextChar);
}
}
@@ -1970,6 +1972,7 @@ public class DocumentationManager extends DockablePopupManager\\s*(<(?:[uo]l|h\\d|p|tr|td))", "$1");
text = addExternalLinksIcon(text);
+ text = DocumentationHtmlUtil.addWordBreaks(text);
return text;
}
diff --git a/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt b/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt
index e2e41e5a0b32..eab2bb93724e 100644
--- a/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt
+++ b/platform/lang-impl/src/com/intellij/lang/documentation/QuickDocHighlightingHelper.kt
@@ -289,7 +289,6 @@ object QuickDocHighlightingHelper {
"li { padding: ${scale(1)}px 0 ${scale(2)}px 0; }",
"li p { padding-top: 0; padding-bottom: 0; }",
"th { text-align: left; }",
- "table { width: 100%}",
"tr, table { margin: 0 0 0 0; padding: 0 0 0 0; }",
"td { margin: 0 0 0 0; padding: 0 0 ${spacing}px 0; }",
"td p { padding-top: 0; padding-bottom: 0; }",
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt b/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt
index 0cace6532832..ad76f2563bbc 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt
+++ b/platform/platform-impl/src/com/intellij/ide/ui/html/StyleSheetRulesProviderForCodeHighlighting.kt
@@ -79,6 +79,8 @@ object StyleSheetRulesProviderForCodeHighlighting {
if (enableInlineCodeBackground) {
val selectors = inlineCodeParentSelectors.asSequence().map { "$it code" }.joinToString(", ")
result.add("$selectors $codeColorStyle")
+ // 'caption-side' is a hack to support 'border-radius'.
+ // See also: com.intellij.util.ui.html.InlineViewEx
result.add("$selectors { padding: 1px 4px; margin: 1px 0px; caption-side: 10px; }")
}
if (enableCodeBlocksBackground) {
diff --git a/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt b/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt
index 0bbae2e0d913..1d152535ebca 100644
--- a/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt
+++ b/platform/util/ui/src/com/intellij/util/ui/ExtendableHTMLViewFactory.kt
@@ -6,9 +6,10 @@ import com.intellij.openapi.util.IconLoader
import com.intellij.openapi.util.text.HtmlChunk
import com.intellij.ui.scale.JBUIScale
import com.intellij.util.text.nullize
+import com.intellij.util.ui.html.FitToWidthImageView
import com.intellij.util.ui.html.HiDpiScalingImageView
import com.intellij.util.ui.html.InlineViewEx
-import com.intellij.util.ui.html.FitToWidthImageView
+import com.intellij.util.ui.html.WbrView
import java.awt.*
import java.awt.image.BufferedImage
import java.io.ByteArrayInputStream
@@ -48,7 +49,7 @@ class ExtendableHTMLViewFactory internal constructor(
companion object {
@JvmField
val DEFAULT_EXTENSIONS: List = listOf(Extensions.ICONS, Extensions.BASE64_IMAGES, Extensions.HIDPI_IMAGES,
- Extensions.INLINE_VIEW_EX)
+ Extensions.INLINE_VIEW_EX, Extensions.WBR_SUPPORT)
@JvmField
val DEFAULT: ExtendableHTMLViewFactory = ExtendableHTMLViewFactory(DEFAULT_EXTENSIONS)
@@ -134,6 +135,12 @@ class ExtendableHTMLViewFactory internal constructor(
@JvmField
val FIT_TO_WIDTH_IMAGES: Extension = FitToWidthImageViewExtension()
+ /**
+ * Adds support for `` tags
+ */
+ @JvmField
+ val WBR_SUPPORT: Extension = WbrSupportExtension()
+
private class IconsExtension(private val existingIconsProvider: (key: String) -> Icon?) : Extension {
constructor(preloadedIcons: Map) : this(preloadedIconsProvider(preloadedIcons))
@@ -361,7 +368,7 @@ class ExtendableHTMLViewFactory internal constructor(
}
}
- private class InlineViewExExtension: Extension {
+ private class InlineViewExExtension : Extension {
override fun invoke(element: Element, view: View): View? {
if (view.javaClass != InlineView::class.java) return null
val attrs = view.attributes
@@ -381,10 +388,18 @@ class ExtendableHTMLViewFactory internal constructor(
}
}
- private class FitToWidthImageViewExtension: Extension {
+ private class FitToWidthImageViewExtension : Extension {
override fun invoke(element: Element, view: View): View? =
if (view is ImageView) FitToWidthImageView(element) else null
}
+
+ private class WbrSupportExtension : Extension {
+ override fun invoke(elem: Element, defaultView: View): View? =
+ if (elem.name.equals("wbr", true))
+ WbrView(elem)
+ else
+ null
+ }
}
private class HiDpiImagesExtension : ExtendableHTMLViewFactory.Extension {
diff --git a/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt b/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt
index 704a69203cdc..c28b12b8fa1d 100644
--- a/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt
+++ b/platform/util/ui/src/com/intellij/util/ui/html/InlineViewEx.kt
@@ -46,20 +46,6 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) {
override fun setPropertiesFromAttributes() {
super.setPropertiesFromAttributes()
- val parentView = parent
- val index = (0..parentView.viewCount).firstOrNull { parentView.getView(it) === this } ?: -1
-
-
- // Heuristics to determine whether we are within the same inline (e.g. ) element with paddings.
- // Nested inline element insets are not supported, because hierarchy of inline elements is not preserved.
- val prevSibling = if (index > 0) parentView.getView(index - 1) else null
- val nextSibling = if (index < parentView.viewCount - 1) parentView.getView(index + 1) else null
-
- padding = this.cssPadding
- margin = this.cssMargin
-
- startView = prevSibling?.cssPadding != padding || prevSibling.cssMargin != margin
- endView = nextSibling?.cssPadding != padding || nextSibling.cssMargin != margin
// "caption-side" is used as "border-radius"
borderRadius = attributes.getAttribute(CAPTION_SIDE)
@@ -69,27 +55,7 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) {
?.toIntOrNull()
?.let { JBUI.scale(it) }
?: 0
-
- padding.set(
- padding.top,
- if (startView) padding.left else 0,
- padding.bottom,
- if (endView) padding.right else 0,
- )
-
- margin.set(
- margin.top,
- if (startView) margin.left else 0,
- margin.bottom,
- if (endView) margin.right else 0,
- )
-
- insets = JBInsets(
- padding.top + margin.top,
- padding.left + margin.left,
- padding.bottom + margin.bottom,
- padding.right + margin.right,
- )
+ updatePaddingsAndMargins(true)
}
override fun getPartialSpan(p0: Int, p1: Int): Float {
@@ -103,12 +69,14 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) {
return offset + super.getPartialSpan(p0, p1)
}
- override fun getPreferredSpan(axis: Int): Float =
- super.getPreferredSpan(axis) + when (axis) {
+ override fun getPreferredSpan(axis: Int): Float {
+ updatePaddingsAndMargins(false)
+ return super.getPreferredSpan(axis) + when (axis) {
View.X_AXIS -> insets.width()
View.Y_AXIS -> insets.height()
else -> throw IllegalArgumentException("Invalid axis: $axis")
}
+ }
override fun getTabbedSpan(x: Float, e: TabExpander?): Float =
super.getTabbedSpan(x, e) + insets.width()
@@ -173,4 +141,59 @@ internal class InlineViewEx(elem: Element) : InlineView(elem) {
return super.getAlignment(axis)
}
+ private fun getSibling(parentView: View, curIndex: Int, direction: Int): View? {
+ var siblingIndex = curIndex + direction
+ val viewCount = parentView.viewCount
+ while (siblingIndex in 0..) element with paddings.
+ // Nested inline element insets are not supported, because hierarchy of inline elements is not preserved.
+ val prevSibling = getSibling(parentView, index, -1)
+ val nextSibling = getSibling(parentView, index, 1)
+
+ val cssPadding = this.cssPadding
+ val cssMargin = this.cssMargin
+
+ val startView = prevSibling?.cssPadding != cssPadding || prevSibling.cssMargin != cssMargin
+ val endView = nextSibling?.cssPadding != cssPadding || nextSibling.cssMargin != cssMargin
+
+ if (!force && startView == this.startView && endView == this.endView) {
+ return
+ }
+ this.startView = startView
+ this.endView = endView
+
+ padding = JBInsets(
+ cssPadding.top,
+ if (startView) cssPadding.left else 0,
+ cssPadding.bottom,
+ if (endView) cssPadding.right else 0,
+ )
+
+ margin = JBInsets(
+ cssMargin.top,
+ if (startView) cssMargin.left else 0,
+ cssMargin.bottom,
+ if (endView) cssMargin.right else 0,
+ )
+
+ insets = JBInsets(
+ padding.top + margin.top,
+ padding.left + margin.left,
+ padding.bottom + margin.bottom,
+ padding.right + margin.right,
+ )
+ }
+
}
\ No newline at end of file
diff --git a/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt b/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt
new file mode 100644
index 000000000000..932579c24d1c
--- /dev/null
+++ b/platform/util/ui/src/com/intellij/util/ui/html/WbrView.kt
@@ -0,0 +1,38 @@
+// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.util.ui.html
+
+import java.awt.Shape
+import javax.swing.text.Element
+import javax.swing.text.Position
+import javax.swing.text.Segment
+import javax.swing.text.View
+import javax.swing.text.html.InlineView
+
+class WbrView(elem: Element) : InlineView(elem) {
+
+ override fun getMinimumSpan(axis: Int): Float = 0f
+
+ override fun getMaximumSpan(axis: Int): Float =
+ if (axis == View.X_AXIS)
+ 0f
+ else
+ Int.MAX_VALUE.toFloat()
+
+ override fun getViewIndex(pos: Int, b: Position.Bias?): Int = -1
+
+ override fun getViewIndex(x: Float, y: Float, allocation: Shape?): Int = -1
+
+ override fun getResizeWeight(axis: Int): Int = 0
+
+ override fun setSize(width: Float, height: Float) {
+ super.setSize(0f, 0f)
+ }
+
+ override fun getPreferredSpan(axis: Int): Float = 0f
+
+ override fun getText(p0: Int, p1: Int): Segment = Segment()
+
+ override fun breakView(axis: Int, offset: Int, pos: Float, len: Float): View = this
+
+ override fun getBreakWeight(axis: Int, pos: Float, len: Float): Int = ExcellentBreakWeight
+}
\ No newline at end of file
|