SDK in other IDE is not indexed

已回答

Hello I've got question about SDK.

I have plugin where SDK contains built-in classes / methods and need to add it and index it.

In IntelliJ I've used regular IDE project settings to add it, but that UI is missing in f.e. Rider, so I've moved it into custom plugin settings, where I select SDK path and create it programatically - for IntelliJ it works fine, but in Rider even when I create SDK like this, it is not parsed and indexed so classes remain unknown - but everything works fine without an error, it's just not indexed.

From comments I've read that ProjectJdkTable despite it's name should be usable for all types of SDK not just Java, but outside of IntelliJ I can't get it recognized/indexed.

The code I'm using:

// Setup new SDK if it does not exist
val
projectSdks = ProjectJdkTable.getInstance().allJdks;
if (projectSdks.any { it.sdkType is GdSdkType }) { val newSdkName = SdkConfigurationUtil.createUniqueSdkName(GdSdkType, "", projectSdks.toList()); val newJdk = ProjectJdkImpl(newSdkName, GdSdkType); GdSdkType.setupSdkPaths(newJdk); ApplicationManager.getApplication().invokeAndWait { runWriteAction { if (ProjectJdkTable.getInstance().allJdks.any { it.sdkType is GdSdkType }) return@runWriteAction; ProjectJdkTable.getInstance().addJdk(newJdk); } } }
}


// Register SDK root folder
val projectSdks = ProjectJdkTable.getInstance().allJdks; val sdk = projectSdks.find { it.sdkType is GdSdkType }?.sdkModificator ?: return; if (sdk !is ProjectJdkImpl) return; sdk.removeAllRoots();
val pathUrl = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, path); sdk.addRoot(pathUrl, OrderRootType.CLASSES); sdk.commitChanges();

I've even tried to set it up as Projects SDK like:

val project = ProjectManager.getInstance().defaultProject;
ProjectRootManager.getInstance(project).projectSdk = sdk;

But for IntelliJ this was not needed and in Rider on the other hand that caused an error of editing readOnly files (maybe 

0

Tested today to change SDK for a library but the result is still the same - added files are not getting indexed.

val project = ProjectManager.getInstance().defaultProject;
val table = LibraryTablesRegistrar.getInstance().getLibraryTable(project);
val pathUrl = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, path);

ApplicationManager.getApplication().invokeAndWait {
runWriteAction {
val newLib = table.createLibrary(LIBRARY_NAME);
val libModel = newLib.modifiableModel;
libModel.addRoot(pathUrl, OrderRootType.SOURCES);
libModel.commit();
}
}

Does anyone have an idea, how to get those external files indexed so it's useable for language validators, completions and such? Is there any documentation / working example somewhere that is not for IntelliJ where it works.

0

Hi,

Is it not indexed only in Rider or also in other non-IDEA IDEs?

0

Tested PhpStorm and it works fine in it, right after SDK is added it successfully index it's content.

Sadly Rider is required as this plugin is gonna be used with C# projects.

0

Could you please tell us more about the purpose of this custom SDK?

I have plugin where SDK contains built-in classes / methods and need to add it and index it.

Is this about Java classes? What should happen after you "index" them? Should they resolve somewhere in the editor afterwards?

0

I'm trying to create a Standard Library... list of built-in classes available in empty project, built-in functions

They are resolved inside editor f.e. when I extend my class by one of them, call a function it contains and such.

So class names, functions, properties are all checked from indices.

EDIT: and no Java it has nothing to do with Java, but I expected that SDK should work the same regardless of language.

0

Could you please tell us more about the "Standard Library"? Is it .NET?

I expected that SDK should work the same regardless of language.

Unfortunately, the reality is much more complex than that :(

So please elaborate on what exactly are you doing, and we'll try to help.

0

No, it's a GdScript from Godot - so completly unrelated language. 

The reason why I need Rider is because Godot projects can use both GdScript & C# simultaneously.

That Library I'm trying to create is a separate folder with GdScript files providing basic classes (which are integral part of Godot). I need to include those files into project so they are visible for extending/calling  it's functions and such -> those files are not meant to be edited as they are provided by Godot itself and are included into all Godot projects by default.

My idea was/is to provide .zip with those GdScript files. User will download it and then inside plugin settings adds a path to this. Then I programatically take this path, create SDK/Library and register it into project.

This way I hoped that it will be indexed - so it's classes become visible the same way as if they were inside the project folder itself.

And in Intellij & PhpStorm that works, sadly Rider works little different it seems.

 

Or is there a better approach for it? I hope you understand now what I'm trying to do.

Should it be somehow (don't know how) included in the plugin itself and not be separate like that, I don't know how to index those GdScript files, should they be bundled into plugin itself.

 

I'd say it's same as this question f.e.:

https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000570810-Create-a-custom-SDK-or-standard-library-for-custom-language

0

Hi, can anyone help me with it, please?

0

The very first problem here - missing virtual files. Could you try to refresh VFS and find a virtual file before creating a library. The second issue - probably we have to attach library to a module (in case of rider there is only one "general" module).

val project = ProjectManager.getInstance().defaultProject;
val table = LibraryTablesRegistrar.getInstance().getLibraryTable(project);
val virtualFile = VfsUtil.findFileByIoFile(File(path), true);

ApplicationManager.getApplication().invokeAndWait {
runWriteAction {
val newLib = table.createLibrary(LIBRARY_NAME);
val libModel = newLib.modifiableModel;
libModel.addRoot(virtualFile.url, OrderRootType.SOURCES);
libModel.commit();

 val module = ModuleManager.getInstance(project).modules.first()
val rootModel = ModuleRootManager.getInstance(module).modifiableModel
      rootModel.addLibraryEntry(newLib)
      rootModel.commit()
}
}
2

Thank you, I've tried it, but in both IntelliJ & Rider I've run into an issue, that

ModuleManager.getInstance(project).modules

is always empty, which is weird even more so for IntelliJ, where in Project Structure I do see Java Module... maybe it does not list it because my plugin is for different Language (GdScript)?

And creating a new module from code throws an Exception of:

ModuleManager.getInstance(project).newModule(path, "GD_MODULE")

java.lang.ClassCastException: class com.intellij.openapi.project.impl.DefaultProject cannot be cast to class com.intellij.serviceContainer.ComponentManagerImpl (com.intellij.openapi.project.impl.DefaultProject and com.intellij.serviceContainer.ComponentManagerImpl are in unnamed module of loader com.intellij.util.lang.PathClassLoader @1ff8b8f)

I'll try do dive deeper into Modules later on to try figure it out, but so far still no luck with it.

0

I've came up with an ugly workaround using IndexableSetContributor

override fun getAdditionalProjectRootsToIndex(project: Project): MutableSet<VirtualFile> {
val path = GdSettingsState.getInstance().state.sdkPath;
if (!path.isNullOrBlank()) {
val virtualFile = VfsUtil.findFileByIoFile(File(path), true);
roots.add(virtualFile!!);
}

return roots;
}

Where I simply add root to index from settings.

Yet even though I managed to make this work, for some reason I cannot use 

GlobalSearchScope.allScope(project)

When looking into index - even when using

getAdditionalProjectRootsToIndex()

instead of 

getAdditionalRootsToIndex()

But at least it works with:

GlobalSearchScope.everythingScope(project)

Is there some reason why additionProjectRootToIndex would be excluded from allScope? I understand that it's not in projectScope, but would expect to work with allScope.

0

Can not tell about IDEA, but in Rider scopes work based on MSBuild project model. Probably we will be able to fix that for your case :)

About `defaultProject` - you should not use it, get a proper project from IdeFrame or another place. 

1

Ou awesome - had no idea how else to get Project instance.

Getting it from IdeFrame instead of defaultProject made the Library above work - module is present, library files get indexed and it does work with allScope(project) as well in both IntelliJ & Rider, so I can drop IndexableSetContributor.

Thank you very much and have a nice day.

0

There are many ways to get a project. From a project service (via injection into constructor), from a parameter of an startup activity, from AnActionEvent, from (almost) any DataContext, from UI (and you already did it)... 

I am glad I was able to help :) 

0

请先登录再写评论。