Handling library modifications before the IDE is loaded
Hello,
I'm working on a plugin for Jetbrains IDEs that adds support for working with MicroPython. One of the plugin's features is a built-in stub package manager that let's the users select and activate board and version specific stub packages for better code analysis.
In order to achieve this I have to work with the library table. However, I've ran into a problem. If the library is modified too early, before the IDE is fully loaded/indexed the library change might have no effect and instead an different package that was attached previously will get applied.
In order to prevent this I tried to use DumbService.getInstance(project).smartInvokeLater but this seems to have changed nothing.
I'm considering creating a start-up activity and having it repeatedly check the library every 5-10 seconds and then calling the updateLibrary() method whenever there is a mismatch between the library selected by the user and between the library that is actually loaded. But I want to ask, is there a better way to work with the libraries in order to solve this problem?
Here is the the function I have currently:
fun updateLibrary() {
val settings = project.service<MpySettingsService>()
val activeStubPackage = settings.state.activeStubsPackage
val availableStubs = getAvailableStubs()
DumbService.getInstance(project).smartInvokeLater {
ApplicationManager.getApplication().runWriteAction {
val projectLibraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable(project)
val projectLibraryModel = projectLibraryTable.modifiableModel
for (library in projectLibraryModel.libraries) {
if (library.name == LIBRARY_NAME) {
projectLibraryTable.removeLibrary(library)
projectLibraryModel.removeLibrary(library)
}
}
if (settings.state.areStubsEnabled &&
!activeStubPackage.isNullOrBlank() &&
availableStubs.contains(activeStubPackage)
) {
val newLibrary = projectLibraryModel.createLibrary(LIBRARY_NAME, PythonLibraryType.getInstance().kind)
val newModel = newLibrary.modifiableModel
val rootUrl = "$stubsPath/$activeStubPackage"
val virtualFile = LocalFileSystem.getInstance().findFileByPath(rootUrl)
newModel.addRoot(virtualFile!!, OrderRootType.CLASSES)
val module = ModuleManager.getInstance(project).modules.first()
val moduleModel = ModifiableModelsProvider.getInstance().getModuleModifiableModel(module)
moduleModel.addLibraryEntry(newLibrary)
newModel.commit()
projectLibraryModel.commit()
ModifiableModelsProvider.getInstance().commitModuleModifiableModel(moduleModel)
} else {
projectLibraryModel.commit()
}
}
}
}
Please sign in to leave a comment.
Your issue with the library not updating correctly is likely due to timing issues during the IDE's startup and indexing process. The use of
DumbService.getInstance(project).smartInvokeLateris a step in the right direction, but it might not be sufficient if the underlying file system and project structures haven't been fully initialized. A better approach than repeatedly checking the library is to use event listeners. Specifically, you should consider listening for project-level events that signal when the project is fully loaded and indexed. Events likeProjectManagerListener.projectOpenedorDumbService.isDumb()becoming false could be good triggers. You can also explore usingStartupActivityand its various forms, but be mindful of theDumbServicestate within it. Instead of repeatedly checking, you could run yourupdateLibrary()logic once, after confirming the project is in a "smart" state (i.e., not indexing).Regards,
Pearl
paybyplatema