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()
            }
        }
    }
}
0
1 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).smartInvokeLater is 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 like ProjectManagerListener.projectOpened or DumbService.isDumb() becoming false could be good triggers. You can also explore using StartupActivity and its various forms, but be mindful of the DumbService state within it. Instead of repeatedly checking, you could run your updateLibrary() logic once, after confirming the project is in a "smart" state (i.e., not indexing).

 

Regards,
Pearl




 

 















paybyplatema

0

Please sign in to leave a comment.