How can I use OpenProjectTask?

I’m trying to implement a ProjectOpenProcessor.

As far as I understand, I’m supposed to call com.intellij.openapi.project.ex.ProjectManagerEx#openProjectAsync in openProjectAsync. This needs a OpenProjectTask, but pretty much everything of OpenProjectTask is internal or restricted.

intellij-community is invoking a builder closure, which is @Internal, too:

@Internal
inline fun OpenProjectTask(buildAction: OpenProjectTaskBuilder.() -> Unit): OpenProjectTask {
  return OpenProjectTaskBuilder().build(buildAction)
}

For example, I want to set OpenProjectTask.projectRootDir, which itself is @Experimental.

But the constructor is @Internal, I can’t instantiate the builder because of internal `@Internal
inline fun OpenProjectTask` and so on.

How is this API supposed to be used by 3rd-party plugins?

Ran into this again with the plugin verifier.

How is OpenProjectTask supposed to be used in 3rd-party plugins?

The entry point to OpenProjectTaskBuilder is @Internal and pretty much everything else, even though there’s @PublishedAPI in the class.

Could you please tell us why do you need it? It is definitely not API for plugins

It has rather different meaning in Kotlin, it does not mean it is public API but enables some inline fun visibility tricks:

/**
 * When applied to a class or a member with internal visibility allows using it from public inline functions and
 * makes it effectively public.
 *
 * Public inline functions cannot use non-public API, since if they are inlined, those non-public API references
 * would violate access restrictions at a call site
 * (see [restrictions for public API inline functions](https://kotlinlang.org/docs/inline-functions.html#restrictions-for-public-api-inline-functions)).
 *
 * To overcome this restriction an `internal` declaration can be annotated with the `@PublishedApi` annotation:
 * - this allows calling that declaration from public inline functions;
 * - the declaration becomes effectively public, and this should be considered with respect to binary compatibility maintaining.
 */
@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
@SinceKotlin("1.1")
public annotation class PublishedApi

I’m implementing a com.intellij.projectImport.ProjectOpenProcessor.

The implementation of openProjectAsync needs to return a Project and I couldn’t find any other way to create a new instance of a Project except with OpenProjectTask. As far as I can tell intellij-community is using the task for its own implementations of openProjectAsync.

If there’s a better way to create a project, please let me know :slight_smile:

We mostly delegate to PlatformProjectOpenProcessor.getInstance().openProjectAsync in newer implementations, which is public

That method is @Internal if I’m not mistaken:

There’s a method on the companioncom.intellij.platform.PlatformProjectOpenProcessor.Companion#openProjectAsync, but it takes a OpenProjectTask.

There’s a non-suspending doOpenProject, but one is deprecated (with an error) and tells to use the other doOpenProject, but that’s @Internal.

This is a huge mistake, it should not be. As in ProjectOpenProcessor it is a normal public function.

As a temporary workaround, you can cast instance to it

Fixes are on the way! https://youtrack.jetbrains.com/issue/IJPL-244518/PlatformProjectOpenProcessor.openProjectAsync-is-mistakenly-marked-ApiStatus.Internal

My colleagues also suggest using ProjectManagerEx.openProjectAsync directly, it is more correct.

Please try in your ProjectOpenProcessor:

ProjectManagerEx.openProjectAsync(Path.of("/home/user/some/project"), projectOpenOptions.toOpenProjectTask())

Thanks!

As far as I understand, the options were only added a few days ago: IJPL-243183 propagate original OpenProjectTask from ProjectUtil.openO… · JetBrains/intellij-community@285ec88 · GitHub

For now, I’ll have to use PlatformProjectOpenProcessor, I think.