TypedHandlerDelegate not being called on every typed character

I have implemented a TypedHandlerDelegate that is supposed to format my code after each keystroke. I have noticed however, that if I type too quickly, then the delegate’s charTyped callback function isn’t being called after the first typed character (according to my observations, this might be related to keydown events happening before the keyup of the previous character). Interestingly, this seems to only happen when starting a new word, if you continue an existing word then everything seems to work as intended no matter how fast you’re typing.

I have already tried adding order="first" in plugin.xml and moving the delegate declaration to the top of the file (per this similar forum post), to no avail.

Has anyone else experienced this issue? Has anyone found a solution for it?

Please share your code and sample scenario file(type).

I tried to send you a minimal reproducible example but couldn’t - the plugin I’m working on is quite big (and proprietary) and it seems like there might be some unwanted interactions between certain parts that stop the delegate’s callback function from being called sometimes. I think it has to do with our inlay hints and/or our completion contributors, and possibly more. I have also noticed that the bigger the file I’m editing is, the more likely it is for this issue to happen (although the file really doesn’t have to be too big for this to become a real annoyance)

What I don’t understand is why order="first" didn’t help with this issue as per my understanding, this piece of code is supposed to ensure that my delegate will get called first, before any of the other extensions (I have also tried order="first, before xy" but that didn’t help either).

Since I can’t share my code, I would appreciate if you could point me towards some resources that would help me ensure that my extensions don’t potentially block each other from being called, or if there are any ways how I could debug this issue, other than painstakingly trying all possible combinations of my extensions until I find the culprit (for example an easy way to observe what extensions are being called when).

The order attribute only defines the order of extensions of the same type, i.e. your handler delegate may be first of it’s kind but other extensions of a different type can be called before, of course. Also, if another handler delegate is also „first“, there‘s no guarantee which extensions is actually first.

The find the culprit, I recommend to set a breakpoint in your handler, find the caller and then debug the logic of the caller to find out why your handler is not being called (use logging breakpoints, for example).
Using a profiler with thread activity monitoring is also useful, I prefer YourKit but AFAIK JetBrains‘s built-in profiler is supporting this, too.

In general, be careful calling a formatter from your handler. iirc it‘s called in a WriteAction and any long-running activity will block the UI. Especially external formatters would slow things down a lot.

Thank you for your answer, I have spent a good amount of time trying to debug this today. It seems I was wrong, since after disabling all but the essential extensions, I am still getting this behavior, although less often (so this issue might be performance related).

Right now I just have three extensions enabled in my plugin.xml: A fileType, a lang.parserDefinition, and my typedHandler. These are needed because we have or own custom language with our own lexer and parser (created with ANTLR4). When typing quickly, the charTyped callback is not called every time after the first typed character.

The formatting functionality inside charTyped is only used on a small part of the entire file, which I would expect to mitigate performance issues. But even if it did slow things down a lot, I would expect the UI to potentially hang, but in theory I should still see the charTyped callback being called after each character, which does not seem to be the case here.

Could you please confirm that this is indeed the intended behavior of this callback? Or are there any reasons why this callback might not be called in certain cases (such as for performance reasons)? I could not find anything about this in the documentation.

It’s best to check the sources.

This is the place where charTyped is called:

As you can see, there are many return statements before this line is reached. Other handlers can prevent your charType from being called.

Is newTypingStarted called as you’d expect it?

I can’t tell if charTyped is really called for every character or if there’s optimizations to skip it on fast typing. I wouldn’t rely on it.

Once again, thank you for your reply - I mistakenly assumed that you’re a JetBrains employee which is why I thought you might know the answer to my question. I have already debugged the file you’ve referenced and found that the doExecute method itself isn’t even being called, so something must be preventing it from being called further down in the code, but I am unable to figure out what exactly. newTypingStarted also isn’t being called properly.

I really need this function to be called on every typed character, or at least when the user has stopped typing (in the case of really fast consequent keypresses), otherwise the user experience is very incosistent as the user ends up with an unformatted file after typing. If this behavior of TypedHandlerDelegate is intended, then it should at least be documented and an alternative solution should be provided in my opinion.

You always can share a minimal reproducible example without your project. We will be able to help then. It is quite easy to create a plugin stub via IDE Plugin wizard and add such an artificial example