Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8301121: RichTextArea Control (Incubator) #1524

Open
wants to merge 63 commits into
base: master
Choose a base branch
from

Conversation

andy-goryachev-oracle
Copy link
Contributor

@andy-goryachev-oracle andy-goryachev-oracle commented Jul 30, 2024

Incubating a new feature - rich text control, RichTextArea, intended to bridge the functional gap with Swing and its StyledEditorKit/JEditorPane. The main design goal is to provide a control that is complete enough to be useful out-of-the box, as well as open to extension by the application developers.

This is a complex feature with a large API surface that would be nearly impossible to get right the first time, even after an extensive review. We are, therefore, introducing this in an incubating module, jfx.incubator.richtext. This will allow us to evolve the API in future releases without the strict compatibility constraints that other JavaFX modules have.

Please check out two manual test applications - one for RichTextArea (RichTextAreaDemoApp) and one for the CodeArea (CodeAreaDemoApp). Also, a small example provides a standalone rich text editor, see RichEditorDemoApp.

Because it's an incubating module, please focus on the public APIs rather than implementation. There will be changes to the implementation once/if the module is promoted to the core by popular demand. The goal of the incubator is to let the app developers try the new feature out.

References


Progress

  • Change must not contain extraneous whitespace
  • Change requires a CSR request matching fixVersion jfx24 to be approved (needs to be created)
  • Commit message must refer to an issue
  • Change must be properly reviewed (2 reviews required, with at least 2 Reviewers)

Warnings

 ⚠️ Patch contains a binary file (apps/samples/RichTextAreaDemo/src/com/oracle/demo/richtext/rta/animated.gif)
 ⚠️ Patch contains a binary file (modules/jfx.incubator.richtext/src/main/docs/jfx/incubator/scene/control/richtext/doc-files/CodeArea.png)
 ⚠️ Patch contains a binary file (modules/jfx.incubator.richtext/src/main/docs/jfx/incubator/scene/control/richtext/doc-files/RichTextArea.png)

Issues

  • JDK-8301121: RichTextArea Control (Incubator) (Enhancement - P2)
  • JDK-8343646: Public InputMap (Incubator) (Enhancement - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jfx.git pull/1524/head:pull/1524
$ git checkout pull/1524

Update a local copy of the PR:
$ git checkout pull/1524
$ git pull https://git.openjdk.org/jfx.git pull/1524/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 1524

View PR using the GUI difftool:
$ git pr show -t 1524

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jfx/pull/1524.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 30, 2024

👋 Welcome back angorya! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Jul 30, 2024

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@andy-goryachev-oracle andy-goryachev-oracle marked this pull request as ready for review July 30, 2024 21:58
@openjdk openjdk bot added the rfr Ready for review label Jul 30, 2024
@andy-goryachev-oracle
Copy link
Contributor Author

/reviewers 3

@openjdk
Copy link

openjdk bot commented Jul 30, 2024

@andy-goryachev-oracle
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 3 (with at least 1 Reviewer, 2 Authors).

* @author Andy Goryachev
* @since 999 TODO
*/
public class RichTextArea extends Control {
Copy link

@danielpeintner danielpeintner Jul 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old TextField and TextArea controls extend TextInputControl.

I wonder whether there is a a good reason not doing the same for RichTextArea?
Doing so would allow to more easily switch between one or the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for a very good question!

The main reason is that RichTextArea (RTA) can work with a large text model which needs to be represented differently from TextInputControl's simple String text property. Other things, like position within the text is also very different, using {paragraphIndex,charOffset} instead of a simple int offset. The fact that the model is separated from the control also makes it very different.

At the end, there is simply no benefit in dragging the TextInputControl into the picture.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping to be able to easily replace one (old) control with the new one. I mean RichTextArea still fulfilling the requirements of TextInputControl. Anyhow, I understand you rational not going along this path 👍

Let me provide the use-case I have in mind (which may explain better what I am looking for).
I would like to use/keep textfields and textareas with pure text. Anyhow, having the possibility to squiggly parts of the text showing spelling mistakes. Since I assume that loading many RichTextArea controls (i.e., in tables) will take much longer I expect to offer spelling suggestions (and RichTextArea loading) on request only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like in this particular case you do want to preserve the semantics and APIs of TextArea, rather than switch to a new API.

You could simply extend TextArea/Skin and add functionality to superimpose the squiggly on top of TextArea. You'll need to listen to several properties and make sure the clipping is set up correctly and you handle the scrolling et cetera, but I think it's doable.

Of course, once you decide that you need to further decorate your text, with let's say highlighted areas, then you might as well use the new component.

By the way, CodeArea is specifically designed for that purpose, even has getText() and setText() - but no textProperty because it's designed to work with large documents.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might be right about impact on performance when trying to use many RichTextArea (RTA) controls as table cells - it is indeed a heavier component, but as long as you ensure there are no memory leaks and your table does not show 1000s of cells on screen we should be ok.

If performance is an issue, a full blown editor might indeed be overkill, and you might be better off created a subclass of Labeled adorned with decorations instead. You can always set up RTA as an editor if you need to.

@andy-goryachev-oracle
Copy link
Contributor Author

/csr

@openjdk openjdk bot added the csr Need approved CSR to integrate pull request label Jul 31, 2024
@openjdk
Copy link

openjdk bot commented Jul 31, 2024

@andy-goryachev-oracle has indicated that a compatibility and specification (CSR) request is needed for this pull request.

@andy-goryachev-oracle please create a CSR request for issue JDK-8301121 with the correct fix version. This pull request cannot be integrated until the CSR request is approved.

@andy-goryachev-oracle
Copy link
Contributor Author

/reviewers 2 reviewers

@kevinrushforth kevinrushforth self-requested a review August 1, 2024 22:16
@openjdk
Copy link

openjdk bot commented Aug 1, 2024

@andy-goryachev-oracle
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 2 Reviewers).

@andy-goryachev-oracle
Copy link
Contributor Author

/reviewers 3

@openjdk
Copy link

openjdk bot commented Aug 1, 2024

@andy-goryachev-oracle
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 3 (with at least 1 Reviewer, 2 Authors).

@andy-goryachev-oracle
Copy link
Contributor Author

how do I set 3 reviewers and at least 2 "R"eviewers?

@kevinrushforth
Copy link
Member

how do I set 3 reviewers and at least 2 "R"eviewers?

You can't. You can set it to /reviewers 2 reviewers and ask others to also review.

@andy-goryachev-oracle
Copy link
Contributor Author

/reviewers 2 reviewers

@openjdk
Copy link

openjdk bot commented Aug 1, 2024

@andy-goryachev-oracle
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 2 Reviewers).

* Should not be called with localY outside of this layout sliding window.
*/
private int binarySearch(double localY, int low, int high) {
//System.err.println(" binarySearch off=" + off + ", high=" + high + ", low=" + low); // FIX
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like remnants of the debugging session. Do you still need it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, indeed it is (to be cleaned up later).
I would encourage the reviewers to focus on the public API rather than the implementation at this stage.

@@ -446,6 +446,16 @@ <h2>Contents</h2>
</li>
</ul>
</li>
<li><a href="#incubator-modules">Incubator Modules</a>
<ul>
<li>jfx.incubator.scene.control.rich
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

module name typo : rich -> richtext

<table class="package" width="100%">
<tbody>
<tr>
<td>jfx.incubator.scene.control.rich</td>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

module name typo : rich -> richtext

<li>jfx.incubator.scene.control.rich
<ul>
<li><a href="#codearea">CodeArea</a></li>
<li><a href="#richtextarea">RichTextArea</a></li>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order of these 2 items should be reversed to match order present in the description.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the general convention is to list the classes in alphabetical order.

public interface SyntaxDecorator {
/**
* Creates a {@link RichParagraph} from the paragraph plain text.
* The text string is guaranteed to contain neither newline nor carriage return symbols.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment seems unclear to me. Which text string ? There is no String parameter here, only a CodeTextModel with a paragraph index...

Copy link
Contributor Author

@andy-goryachev-oracle andy-goryachev-oracle Aug 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to rework the javadoc here. Thank you!

* This content provides in-memory storage in an {@code ArrayList} of {@code String}s.
*/
public static class InMemoryContent implements Content {
private final ArrayList<String> paragraphs = new ArrayList<>();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since paragraphs may be inserted anywhere, I would guess that using a LinkedList should be more efficient here. Otherwise, when adding a line break somewhere in the middle of a long text, a lot of array members must be copied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, but this is just a default implementation. you can still implement your own BasicTextModel.Content and pass it to the constructor.

Do you want to see an in-memory implementation optimized for large number of paragraphs or should it better be left up to the app developers?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we should definitely provide a very efficient implementation, because most app developers will not want to change it. We should definitely avoid another "TextArea situation", where the application breaks apart, if the text grows too big.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am strongly against LinkedList here: not only it adds 2 pointers to each element, but mostly because it provides no random access.

ArrayList should be sufficient for simple cases, and the developers are free to implement a better Content for their use case. Maybe it's a skip list, or BPlusTree, or something else.

I would also like to mention that the performance issue with TextArea is not the storage (at least it is not the first order issue), but the fact that it renders all the text (in a single Text node). RTA renders only the sliding window, which should be much faster. Of course, RTA will have issues with very long paragraphs, but that's a different story (and is mentioned in the Non-Goals section)

https://github.com/andy-goryachev-oracle/Test/blob/main/doc/RichTextArea/RichTextArea.md#non-goals

}

@Override
public RichParagraph createRichParagraph(CodeTextModel model, int index) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When implementing "real" syntax highlighting, the style of a paragraph will depend on the style of it's predecessors (e.g. multiline strings or multiline comments)...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, this is just a demo.

The information passed to the SyntaxDecorator interface should be sufficient to support any "real" syntax, at least I hope it is. We are passing the model to each method, so it can re/construct the syntax or cache it as needed.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider this situation: When a user types some text into paragraph 2, it may change the styling in paragraph 2, 3, 4, ...
Will the createRichParagraph - method be called for each paragraph after each typed character? That would probably be inefficient; On the other hand, if it is only called for the paragraph the user typed in, that may not be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case the model fires a change event which defines the affected area. The view (the skin) determines which visible elements need to be updated, by calling StyledTextModel::getParagraph().

I don't think there will be efficiency issues because

  1. these visuals are likely to be updated anyway
  2. the number of requested paragraphs is limited by the size of the sliding window (i.e. screen size + some margin)

@openjdk openjdk bot added the rfr Ready for review label Oct 30, 2024
Copy link
Member

@kevinrushforth kevinrushforth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you addressed all of my earlier comments. I left a few comments and questions inline.

@@ -682,6 +690,16 @@ public final StyledTextModel getModel() {
return model == null ? null : model.get();
}

/**
* Validates the model property value.
* The subclass should override this method to check if the model type is supported and throw a TBD if not.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"TBD" --> "IllegalArgumentException".

Also, you might want to add something like: "... should override this method if it restricts the type of model that is supported ..." (since a subclass that takes all types of model need not override it).

/**
* Validates the model property value.
* The subclass should override this method to check if the model type is supported and throw a TBD if not.
* A {@code null} value should never generate the exception.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"the exception" --> "an exception".

@@ -65,6 +65,7 @@ public interface Content {

/**
* This method is called to insert a single text segment at the given position.
* The caller guarantees that this method is only called when the content is writable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a public method that could be called by an application, I think you still need to describe what happens if the caller does call when not writable.

Copy link
Contributor Author

@andy-goryachev-oracle andy-goryachev-oracle Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the implementor of the Content can do whatever they want - I don't think we should specify that.

In the case of BasicTextModel.Content, I think it's important to mention that the caller (the BasicTextModel) will never do.

maybe caller -> BasicTextModel

Also, I think there should be some code added to the RTA/StyledTextModel to ensure that paragraph indexes and TextPos'itions are never go beyond the range allowed by the model (it's in my list).

* Because it is immutable, it cannot track locations in the document which is being edited.
* For that, use {@link Marker}.
*/
public final class TextPos implements Comparable<TextPos> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A record seems more natural here, so would be the default choice, but if there is a good reason not to, I don't see it as a requirement.

* @param offset the text offset
* @return the instance of {@code TextPos}
*/
public static TextPos ofLeading(int index, int offset) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you also plan to add an ofTrailing convenience method?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessary - this case is more complex and is covered by the constructor.

@@ -5795,6 +5993,7 @@ compileTargets { t ->
def modnames = []
moduleProjList.each { project ->
if (project.hasProperty("moduleName") && project.buildModule) {
def incubating = project.hasProperty("incubating") && project.ext.incubating
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the merge of master, you can remove this (it is unused). I removed it from the PR #1616 (Support JavaFX incubator modules).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I plan to update (merge) the build script once #1616 is integrated.

@@ -99,10 +99,10 @@ public class Params {
public static final double MIN_VIEWPORT_WIDTH = 10;

/** default preferred height */
public static final double PREF_HEIGHT = 100;
public static final double PREF_HEIGHT = 176; // matches TextArea
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see 181 as TextArea height, at least on Windows. I think it is computed from the default number of columns visible. I didn't check on macOS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not the goal to match the TextArea, especially if the latter is different on different platforms.


/** default preferred width */
public static final double PREF_WIDTH = 200;
public static final double PREF_WIDTH = 176; // matches TextArea
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see 478 for TextArea width on Windows.

*
* <h2>Usage Considerations</h2>
* {@code CodeArea} extends the {@link RichTextArea} class, meaning most of the functionality is expected to continue
* working. There are some differences that should be mentioned:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: "... meaning most of the functionality works as it does in the base class" or similar?

* <li>Model behavior: any direct changes to the styling, such as
* {@link #applyStyle(TextPos, TextPos, jfx.incubator.scene.control.richtext.model.StyleAttributeMap) applyStyle()},
* will be ignored
* <li>Line numbers: the line numbers are provided by setting the {@link #leftDecoratorProperty()}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be misconstrued to mean that the app should set the leftDecoratorProperty to provide line numbers. I would reword it to make it clear that CodeArea itself sets leftDecoratorProperty so applications should not.

@PavelTurk
Copy link

PavelTurk commented Nov 5, 2024

Currently we use RichTextFX and the problem is that it doesn't support caret form (see FXMisc/RichTextFX#1121) . I've just checked RichTextArea CSS guide and found there -fx-caret-blink-period. I suggest to add at least -fx-caret-shape with all well-known shapes, like bar etc. Besides -fx-caret-color would be nice.

@andy-goryachev-oracle
Copy link
Contributor Author

I suggest to add at least -fx-caret-shape with all well-known shapes, like bar etc. Besides -fx-caret-color would be nice.

Thank you for the feedback!

I wanted not to complicate the first round with different carets. Nevertheless, it should be possible to either support some of the caret types out of the box, or allow for customization.

The default caret shape may need to depend on the input locale and/or presence of RTL or mixed text - something is yet to be fully addressed due to existing bugs, see https://bugs.openjdk.org/browse/JDK-8343557

Another topic is the "block caret", which, in my opinion, only makes sense with the monospaced font, maybe in the CodeArea. I don't know how the block caret should look with the proportional fonts, or when navigating grapheme clusters (a bit of a pain point at the moment).

And lastly, .caret is a Path, so it can be styled with the CSS, see RichTextAreaDemoPane:183
I don't know whether additional styleable property is needed, since the app can just use the stylesheet or inline style, but I can be wrong.

Also (you know this already, but the wider audience may not): there is ongoing work in https://bugs.openjdk.org/browse/JDK-8341670 to expose more detail about the caret geometry (among other things) that should help third party devs with creating custom carets.

Thanks again!

@andy-goryachev-oracle
Copy link
Contributor Author

/issue add 8343646

@openjdk
Copy link

openjdk bot commented Nov 5, 2024

@andy-goryachev-oracle
Adding additional issue to issue list: 8343646: Public InputMap (Incubator).

@andy-goryachev-oracle
Copy link
Contributor Author

the problem is that it doesn't support caret form

@PavelTurk there was a discussion re: caret with mixed text here
#1220

This PR is closed now, but the issue (https://bugs.openjdk.org/browse/JDK-8296266) is still there and I hope to eventually resolve it.
Feel free to join the discussion (in the mailing list or the JBS ticket).

Copy link
Member

@arapte arapte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Providing a few comments. I shall continue to review.

# Incubator

This project incubates
[InputMap](src/main/java/javafx/incubator/scene/control/rich/RichTextArea.java)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link seems to be incorrect.

Comment on lines 4 to 6
[InputMap](src/main/java/javafx/incubator/scene/control/rich/RichTextArea.java)

Please refer to this [README](/tests/manual/RichTextAreaDemo/README.md).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be a pointer to exact sample which uses the new InputMap classes would be good here.

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright year correction, may be it should be done as the last item before final push. (just in case if the PR reaches year 2025)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the copyright dates reflect the years the code became visible to the public.
it will be updated in 2025 if necessary.

private static final int RELEASED = 0x02;
private static final int TYPED = 0x04;

private int types;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, the 3 event types are mutually exclusive, either a key would be pressed or released or typed.
so the name of this variable should be a singular form type or preferably eventType

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all these are private fields of an internal implementation

Comment on lines 41 to 42
public KeyEventMapper() {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be remove empty default ctor.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why? this class is not exposed.

}
}
}
return items.size() == 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use of ArrayList.isEmpty() would look nicer.
return items.size() == 0; -> return items.isEmpty();


@Override
public String toString() {
return "PHList" + items;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return "PHList:" + items; -> return "PHList{items=" + items + "}";

Comment on lines +70 to +72
if (handler != null) {
insert(++ix, handler);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to store the priority when the handler is null.
Will it be safe to simply return at beginning of the method when handler == null ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it's important to store the priority.
this is an implementation detail

insert(++ix, handler);
}
} else {
insert(ix, handler);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is if (handler != null) check required here as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

}
}
}
return items.size() == 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use of ArrayList.isEmpty() would look nicer.
return items.size() == 0; -> return items.isEmpty();

@openjdk openjdk bot removed the rfr Ready for review label Nov 15, 2024
@openjdk openjdk bot added the rfr Ready for review label Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
csr Need approved CSR to integrate pull request rfr Ready for review
Development

Successfully merging this pull request may close these issues.

10 participants