-
Notifications
You must be signed in to change notification settings - Fork 148
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
Register Context Commands with already added types #399
Conversation
Thanks for wading into this! That constructor is getting to be a bruiser (which is not your fault, at all). I wonder if we should start wrapping some of these long constructors into |
@@ -166,9 +168,7 @@ export class LSPExtension implements ILSPExtension { | |||
console.error(reason.message); | |||
}); | |||
|
|||
adapterManager.registerExtension(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the ordering of this line and the connect
below doesn't matter, perhaps we could:
connect
firstresigterExtension
- have
registerExtension
(which I assume can only be called once?) dothis.types.foreach((t) => this.adapterTypeAdded.emit(t))
- have
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this idea! In addition, it is worth noting that registerExtension
already does two loops (one to connect to already registered adapters and second to watch for future registrations), so it seems like a natural place to address this problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you both for your quick response!
It sounds like a good idea; but I do have concerns (maybe they are unfounded).
If we do reemit adapterTypeAdded
signal won't we cause potential problems if another extension decides to connect to it and then starts to receive multiple events with the same type?
Also, can we really assume that resigterExtension
can be called only once? If so should we have something in place to enforce that?
Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bollwyvl @krassowski
I am more then happy to make the requested changes; but I thought I will make a small proposal first :)
I made some alterations please have a look and let me know what you think.
Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gah, lost what i was typing. So it goes.
So: it looks like registerExtension
is expecting an LSPExtension
, rather than an ILSPExtension
. I think this kinda signals that it's meant for in-house usage, or would be entirely replaced, rather than having multiple. Perhaps @krassowski can suggest some tactical docstrings. If it can be multiple, then registerAdapterType
probably needs to be added to the interface...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like
registerExtension
is expecting anLSPExtension
, rather than anILSPExtension
. I think this kinda signals that it's meant for in-house usage
yes, this is an accurate description.
Checking out locally... may I recommend a merge/rebase of |
...type.context_menu | ||
}); | ||
this.feature_manager.registerCommandManager(command_manger); | ||
registerAdapterType( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to extraction to a method.
Hooray green. So... how might we test this? We don't expect folks to wade into non-trivial robotframework stuff, but I guess we can have a simple python function that rewrites |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @mnowacki-b, this looks great to me!
@bollwyvl is this ok with you too?
@bollwyvl re-testing - IMO this is very much on the integration-level testing level so I am happy to accept as-is on the JS side.
Of course, the title of the issue tells us that the context menu does not always get initialized. |
Thank you both for the quick turnaround! @krassowski It was an interface glitch. We have a unique way of loading new extensions in our flavor of JupyterLab. We enable them during runtime based on configuration (during JupyterLab initialization). And so those extensions activation is slightly delayed. |
We're very interested in co-developing a stable baseline for an ecosystem around language server features in Lab, but it's pretty tough, as it seems folks are just taking the code and running, and making stuff that isn't compatible with this work... which is totally cool, and why it's open source!
Can you show a tiny example that demonstrates this behavior? If your hacks are occurring too far down the stack (e.g |
By 'our flavor' I meant a custom list of extensions. We do not modify the core JLab we only specify a list of custom extensions that we are interested in. Most of the extensions we use are open sourced with a handful of internal extensions. I still believe this is an issue that may occur as the plugins are loaded asynchronously and the list of adapter type can be updated before |
Perhaps another signal/PromiseDelegate is needed? A thing we resort sometimes for these topics is ASCII art sequence diagrams, drawio pictures, etc. More broadly: I hope I'm not coming off as belligerent: we're at a disadvantage here, as we haven't seen this (mis)behavior in action. If we can work together to reproduce and test it, in a real browser, we can make sure it keeps working. It may mean this is a "custom" lab extension/excursion in CI, but it's work worth doing. Our semi-ridiculous integration suite has been the only we have been able to confidently add new features and extension points, and handle migrations between different JupyterLabs... and things we don't test have definitely regressed. This kind of testing will be much better with the forthcoming jupyterlab 3 work being discussed on #400, where flipping the installed extensions will be measured in milliseconds, not minutes, but I can totally understand if you've got commitments to lab2 (i still ship lab 1 on some projects, because some in-house extensions never updated). |
Totally understand, I can try to see if I can come up with something that can reproduce the issue. |
I put together this rough diagram to demonstrate how this race condition can occur. ILSPAdapterManager: requires: [ILabShell] - emits signal when new adapter type is added `adapterTypeAdded.emit` NOTEBOOK_ADAPTER (@krassowski/jupyterlab-lsp:NotebookAdapter): requires: [ILSPAdapterManager, INotebookTracker] - on activation adds notebook adapter type to `ILSPAdapterManager` ILSPFeatureManager: requires: [ISettingRegistry, ICommandPalette, IDocumentManager, IPaths, IStatusBar, ILSPAdapterManager, ILSPVirtualEditorManager, ILSPCodeExtractorsManager, ILSPCodeOverridesManager] - instantiates LSPExtension which currently in its constructor calls `adapterManager.registerExtension` and `adapterManager.adapterTypeAdded.connect` |
So another aproceh to fix this would be require |
Is there anything I can do to expedite this PR? |
I think that we can merge it as is. I think the current approach is a step forward and even if we do not test against the faulty behaviour, the changes improve the quality of code. Thank you for all the help. |
Thank you! If I may ask; what it your deployment process? how often do you cut releases? |
I will probably do one once #406 is in. Sorry extremely busy week for me. |
@krassowski Thank you! |
References
Issue: https://github.com/krassowski/jupyterlab-lsp/issues/398
Code changes
Registering Context Commands Manager with already added types.
User-facing changes
None
Backwards-incompatible changes
Backword compatible.
Chores