Skip to content

Fix ugly semantic coloring on CSL languages while editing#8011

Closed
lkishalmi wants to merge 1 commit intoapache:masterfrom
lkishalmi:csl-highlighter-fix
Closed

Fix ugly semantic coloring on CSL languages while editing#8011
lkishalmi wants to merge 1 commit intoapache:masterfrom
lkishalmi:csl-highlighter-fix

Conversation

@lkishalmi
Copy link
Copy Markdown
Contributor

This one is bugging me for years.

Whenever I insert or write text to a CSL based editor the semantic coloring does not keep track with the document change
and some text elements get discolored as you type. The next parsing run would then set the colors right.

See the discoloration of permissions before:
Screencast From 2024-12-01 13-04-47.webm

After this fix:
Screencast From 2024-12-01 13-07-58.webm

Fortunately or Unfortunately , I had to change the code here and there in order to be able to understand what's going on.

So this could be a one -liner, removing the Math.min form:

? Math.min(layer.getShiftedPos(element.range.getEnd()), nextElementStartOffset)

I submitted my whole work on this though, hoping that it would simplify that part of CSL and makes it less cryptic.

So my changes in brief (read it with the code changes):

  1. Updated the language level to Java 17
  2. Made SequenceElement as a record. The ComparisonItem got me a lot of headache, at the end it was only used to get the tailSet method work. Interestingly that subset just used as an optimization, the editor works even if the highlight sequence return the whole sequence all the time. (Tested with a 3500+ lines yaml, the performance overhead was barely noticeable.) Yet, I've copied the SortedSet into a list, where a simple binary search could be used to get a partial iterator.
  3. Using just the iterator on GsfHighlightSequence made it a lot simpler.
  4. Initially, I was thinking that the issue is due to some failed/garbage collected weak listener creation/registration, so I moved a few things to lambdas there.
  5. Removed a lot of commented/unused code inherited from Retouche (I think that was the code name of the Java Editor rewrite)

@lkishalmi lkishalmi changed the title Fix ugly semantic coloring on CSL languages Fix ugly semantic coloring on CSL languages while editing Dec 1, 2024
@mbien mbien added this to the NB25 milestone Dec 1, 2024
Copy link
Copy Markdown
Contributor

@matthiasblaesing matthiasblaesing left a comment

Choose a reason for hiding this comment

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

Looks generally sane to me (only eyeballed). My comments are mostly stylistic (you opened the can of worms ;-)).

The one place I'd really like to see improved is documentation, what firstSequenceElement should be doing.

}
}

private static <T> int firstSequenceElement(List<SequenceElement> l, int offset) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A comment what this method should do would be nice. I have a feeling, but knowing would be nice.

public final class GsfSemanticLayer extends AbstractHighlightsContainer implements DocumentListener {

// -J-Dorg.netbeans.modules.csl.editor.semantic.GsfSemanticLayer.level=FINE
private static final Logger LOG = Logger.getLogger(GsfSemanticLayer.class.getName());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LOG is unused and can be removed (reduce warnings).

Comment on lines +62 to +63
private final List<Lookup.Result> coloringResults = new ArrayList<>(3);
private final List<LookupListener> coloringListeners = new ArrayList<>(3);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My take on the reason for this:

Suggested change
private final List<Lookup.Result> coloringResults = new ArrayList<>(3);
private final List<LookupListener> coloringListeners = new ArrayList<>(3);
// Write only - used to keep strong reference to Lookup.Result/LookupListener
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final List<Lookup.Result> coloringResults = new ArrayList<>(3);
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final List<LookupListener> coloringListeners = new ArrayList<>(3);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested by NB:

  • make all fields final
  • use StringBuilder in coloringsToString instead of StringBuffer
  • modifiy coloringsAttributesOrder to private static final Collection<ColoringAttributes> coloringsAttributesOrder = List.of(
  • in parse drop the reassignment of a and move the a.trim() into the valueOf call

Comment on lines +124 to +133
if (language != null) {
ColoringManager manager = language.getColoringManager();
SemanticAnalyzer task = language.getSemanticAnalyzer();
if (manager != null && task != null) {
Parser.Result r = resultIterator.getParserResult();
if (r instanceof ParserResult) {
process(language, (ParserResult) r, newColoring);
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this can be simplified to (manager and task can't be null, at least that is my reading from the code and assured by api annotations).

Suggested change
if (language != null) {
ColoringManager manager = language.getColoringManager();
SemanticAnalyzer task = language.getSemanticAnalyzer();
if (manager != null && task != null) {
Parser.Result r = resultIterator.getParserResult();
if (r instanceof ParserResult) {
process(language, (ParserResult) r, newColoring);
}
}
}
if (language != null) {
Parser.Result r = resultIterator.getParserResult();
if (r instanceof ParserResult parserResult) {
process(language, parserResult, newColoring);
}
}

@mbien mbien added the Code cleanup Label for cleanup done on the Netbeans IDE label Dec 4, 2024
Copy link
Copy Markdown
Member

@mbien mbien left a comment

Choose a reason for hiding this comment

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

Code looks good. Matthias made some good suggestions though.

I vaguely remember the old "schlieman" API impl having a similar problem. The bug could be potentially quite old. Good job hunting it down!

Comment on lines 218 to 220
public int getEndOffset() {
return (element != null)
? Math.min(layer.getShiftedPos(element.range.getEnd()), nextElementStartOffset)
: Integer.MAX_VALUE;
return getShiftedPos(element.range().getEnd());
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

wondering if you could move the fix into its own commit? Even if its just the one liner which removes Math.min.

It would get lost among the other improvements. We do also have a rule in the reviewer guide which states to try to avoid obfuscating fixes with code refactoring. (I know I did break it myself too a few times, but I believe this case here is easy to split still)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well, I probably close this PR and create two new ones. One with the one-line fix, the other is with the code cleanups.

While fixing the issues on HighlightImp, it turned out that it's not used at all.
I guess it is just an old implementation copied over from ...java.semantic package (that one is used), and later it turned out CSL would not use token based Highlighting.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

your choice. Commit messages is all what is left in the repo history once merged. If they describe what they do -> all good. But if you want to split this into two PRs -> also good of course.

@mbien mbien added the ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) label Dec 4, 2024
@mbien mbien added the CSL [ci] enable web job label Dec 4, 2024
@lkishalmi
Copy link
Copy Markdown
Contributor Author

Closing in favor of #8018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) Code cleanup Label for cleanup done on the Netbeans IDE CSL [ci] enable web job Editor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants