Load build.gradle in new project wizard and add additional modules and dependencies

I currently have a new project wizard for my intellij plugin that creates a custom build.gradle file. I am looking to:

  1. Load the project as a gradle project programatically (currently I do this by manually clicking the “load as gradle project” option in the bottom right IDE pop-up). This will create $projectName/main and $projectName/test modules along with their dependencies.
  2. Create a new module $projectName/myMod that depends on $projectName/main and its libraries.

Can someone point me in the right direction for this (examples, APIs of interest, etc.)? Thanks.

Below is what I have currently which is being called in my AssetsStep. However, it is very buggy and doesn’t seem like the proper way to do this.

override fun setupAssets(project: Project) {
	// Create sample code files (including custom build.gradle)
	...
		
	// Load the project as a gradle project
	ApplicationManager.getApplication().invokeLater {
		val projectSettings = GradleProjectSettings().apply {
			externalProjectPath = basePath
			distributionType = DistributionType.WRAPPED
		}

		GradleSettings.getInstance(project).linkProject(projectSettings)

		ExternalSystemUtil.refreshProject(
			basePath,
			ImportSpecBuilder(project, GradleConstants.SYSTEM_ID)
				.withCallback(object : ExternalProjectRefreshCallback {
					override fun onSuccess(externalProject: DataNode<ProjectData>?) {
						// Runs after Gradle import succeeds
						ApplicationManager.getApplication().invokeLater {
							createMyModuleScriptModule(project, project.name, basePath)
						}
					}

					override fun onFailure(errorMessage: String, errorDetails: String?) {
						// Handle failure
						println("ERROR MESSAGE: $errorMessage")
						println("ERROR DETAILS: $errorDetails")
					}
				})
		)
	}
}
	
fun createMyModuleScriptModule(project: Project, projectName: String, basePath: String) {
	ApplicationManager.getApplication().invokeLater {
		WriteAction.run<Throwable> {
			val moduleManager = ModuleManager.getInstance(project)
			val mainModule = moduleManager.findModuleByName("$projectName.main") ?: return@run

			// Create the new module
			val moduleFilePath = "$basePath/.idea/modules/$projectName.myModule.iml"
			val newModule = moduleManager.newModule(moduleFilePath, JavaModuleType.getModuleType().id)

			// Set up its root model
			val rootModel = ModuleRootManager.getInstance(newModule).modifiableModel

			// Add the myModule directory as a source root
			val contentEntry = rootModel.addContentEntry("file://$basePath/myModule")
			contentEntry.addSourceFolder("file://$basePath/myModule", false)

			// Inherit SDK from main module
			rootModel.inheritSdk()

			// Copy all library dependencies from .main module
			val mainRootModel = ModuleRootManager.getInstance(mainModule).modifiableModel
			for (orderEntry in ModuleRootManager.getInstance(mainModule).orderEntries) {
				when (orderEntry) {
					is LibraryOrderEntry -> {
						orderEntry.library?.let { lib ->
							rootModel.addLibraryEntry(lib)
						}
					}
				}
			}
			mainRootModel.dispose()

			// Add .main as a module dependency
			val moduleDependency = rootModel.addModuleOrderEntry(mainModule)
			moduleDependency.isExported = false
			moduleDependency.scope = DependencyScope.COMPILE

			rootModel.commit()
		}
	}
}

Take a look at how StarterModuleImporter used in intellij-community, there are Gradle and Maven implementations used from IntelliJ IDEA wizards to trigger import.

Create a new module $projectName/myMod that depends on $projectName/main and its libraries.

I would heavily recommend not doing this, but instead rely on how Gradle import will do it. There is no way to persist your manual changes to project structure if you in-fact import project from Gradle.

Also you might be interested in dropping all your logic and using StarterModuleBuilder as base instead.

Check JavaFX as an example

Thanks for the advice. Regarding the part on using Gradle instead of creating the modules my myself, I unfortunately am unable to edit build.gradle as it’s a default file (Eclipse and VSCode has an equivalent plugin and they use the same build.gradle file. If I edit it here for IntelliJ, it will reduce the usability of the plugin since I won’t be able to easily open projects that were previously developed using Eclipse/VSCode without making changes to build.gradle). Do you have any recommendations on how to best go about this?

Imagine your user checks out the project from Git next time - no your custom changes from wizard will be applied. So it doesn’t make sense to patch project structure if Gradle is the source of truth, you had better join those modules to the root project together