Skip to content

Conversation

matthiasblaesing
Copy link
Contributor

The CSL/GSF infrastructure of NetBeans provides the basic infrastructure for the editor to highlight other occurrences corresponding to the element the caret is currently being placed on.

For Java and PHP there is an option offered to keep the occurrences, even when the caret is moved of the highlightable element. The occurrences hightlights are then retained until another highlightable element is selected. This is called "Keep Marks" in NetBeans options.

In NB27 for PHP the option to switch "Keep Marks" was wired up, but proved to be problematic. The OccurrenceFinder class, GSF/CSL implementors have to implement, returns highlighting areas. The return consists of indexes into the text content. For normal operation the finder can trivially be run again when the text is modified to update the highlights, this is not the case for the "Keep Marks" case. As the positions of the characters change, caused by deletions and insertions, the highlights can't be updated, as the originating element is not accessible anymore (the caret was moved of it).

The Swing Document class has a solution for this: javax.swing.text.Position. Under the hood CSL/GSF already uses this in the GsfSemanticLayer, so the problem is solved there.

To support "Keep Marks", handling of this configuration has to move to the CSL/GSF level.

In addition to this there is no need to scan for occurrences if the highlighting is disabled, so that also moves to the CSL/GSF layer.

With the infrastructure in place, in addition to Java and PHP (now fixed), support is added for:

  • ANTLR 3
  • ANTLR 4
  • Groovy
  • Expression Language (JSF/JSP)
  • CSS
  • Javascript
  • JSON
grafik grafik

Closes: #8803

…ep Marks" Handling

According to the documentation of OccurrencesFinder the occurrences
scanning should be stateless. The current API holds a calculate and
a getter method, but in the spirit of keeping it mostly stateless,
more state should not be added.

The OccurrencesFinder implementation returns a set of occurrenes
corresponding to the currently highlighted area. These areas are
described by integer arrays (2 elements, start and end index). Given
the return types these areas are only valid until the next edit
occurrs.

On each input the highlights are recalculated. That works fine until
"Keep Marks" is activated. "Keep Marks" keeps the marks, when the caret
is moved of a highlightable variable. If "Keep Marks" is enabled the
marks will be retained then until the caret is placed onto another
highlightable element. The marks in this case must adapt to changes of
the content of the element. Swing Document provides the "Position"
class for this. That class is used by GsfSemanticLayer to hold the
areas returned by the OccurrencesFinder implementation. So to support
"Keep Marks" the CSL/GSF layer has to be aware of this, so that the
GsfSemanticLayer can retain the highlights.

In addition to this there is no need to scan for occurrences if the
highlighting is disabled, so that also moves to the CSL/GSF layer.

Closes: apache#8803
@matthiasblaesing matthiasblaesing added this to the NB28 milestone Sep 17, 2025
@matthiasblaesing matthiasblaesing added API Change [ci] enable extra API related tests PHP [ci] enable extra PHP tests (php/php.editor) Groovy JavaScript [ci] enable web job and extra JavaScript tests (webcommon/javascript2.editor) CSL [ci] enable web job CSS [ci] enable web job enterprise [ci] enable enterprise job ANTLR ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) labels Sep 17, 2025
@troizet
Copy link
Collaborator

troizet commented Sep 18, 2025

@matthiasblaesing I tested the dev build. Everything works great. Thank you very much!

@matthiasblaesing
Copy link
Contributor Author

@lahodaj @junichi11 @tmysik @lkishalmi it would be great if you could have a look at this.

The storage of preferences in the antlr and javascript modules feels a bit strange, but I think it is in line with the established usage in the Java and PHP modules.

The API addition should be safe from my POV. Implementors might already implement the new methods, but I think the names match their usecase, so that should not be a problem. Differing return values would violate the JavaBeans contract.

Copy link
Contributor

@lkishalmi lkishalmi left a comment

Choose a reason for hiding this comment

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

Looked trough this. Nothing jumped out.
Nice work. Thanks!

import org.openide.awt.*;
import org.openide.util.Exceptions;

public class MarkOccurencesPanel extends javax.swing.JPanel {
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick: FQNs used, here and below.


OccurrencesMarkProvider.get(doc).setOccurrences(OccurrencesMarkProvider.createMarks(doc, bag, ES_COLOR, NbBundle.getMessage(MarkOccurrencesHighlighter.class, "LBL_ES_TOOLTIP")));
boolean updateHighlights = false;
if(seqs.isEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if(seqs.isEmpty()) {
if (seqs.isEmpty()) {

updateHighlights = true;
}

if(updateHighlights) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if(updateHighlights) {
if (updateHighlights) {

import javax.swing.JCheckBox;
import org.openide.util.Exceptions;

public class MarkOccurencesPanel extends javax.swing.JPanel {
Copy link
Member

Choose a reason for hiding this comment

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

Nitpick: more FQNs usages, here and possibly in other files.

Copy link
Member

@tmysik tmysik left a comment

Choose a reason for hiding this comment

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

Looks good to me, thank you.

Several classes are very similar, but since they are in different modules, we can hardly (don't want to) do anything about it.

@matthiasblaesing
Copy link
Contributor Author

Pushed changesets with the points raised by @tmysik (these will be squashed before merge).

@mbien
Copy link
Member

mbien commented Sep 21, 2025

its a bit unfortunate that things like this add so much duplicated UI code :( But other than that a great addition of course.

(e.g was working on fixes for the go-to (ctrl+o) dialogs when I saw that its 3 different impls which diverged over time.)

@matthiasblaesing
Copy link
Contributor Author

@mipaaa @troizet @lkishalmi @mbien @tmysik thanks for testing/review/checking.

I intent to merge this by the end of the week unless there are objections raised till then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ANTLR API Change [ci] enable extra API related tests ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) CSL [ci] enable web job CSS [ci] enable web job enterprise [ci] enable enterprise job Groovy JavaScript [ci] enable web job and extra JavaScript tests (webcommon/javascript2.editor) PHP [ci] enable extra PHP tests (php/php.editor)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PHP: The highlight position for marking occurrences is not recalculated after editing the code
5 participants