Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.intellij.java.workspace.entities.JavaResourceRootPropertiesEntity
import com.intellij.java.workspace.entities.JavaSourceRootPropertiesEntity
import com.intellij.java.workspace.entities.javaResourceRoots
import com.intellij.java.workspace.entities.javaSourceRoots
import com.intellij.openapi.externalSystem.autolink.forEachExtensionSafeAsync
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType
import com.intellij.openapi.externalSystem.model.project.IExternalSystemSourceType
import com.intellij.openapi.progress.checkCanceled
Expand Down Expand Up @@ -33,6 +34,8 @@ import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_RESOURCE
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_TEST_ROOT_ENTITY_TYPE_ID
import org.jetbrains.plugins.gradle.model.ExternalProject
import org.jetbrains.plugins.gradle.model.ExternalSourceSet
import org.jetbrains.plugins.gradle.model.GradleLightBuild
import org.jetbrains.plugins.gradle.model.GradleLightProject
import org.jetbrains.plugins.gradle.model.GradleSourceSetModel
import org.jetbrains.plugins.gradle.service.project.GradleContentRootIndex
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil
Expand Down Expand Up @@ -88,7 +91,13 @@ internal class GradleSourceRootSyncContributor : GradleSyncContributor {
val contentRootPaths = contentRootIndex.resolveContentRoots(externalProject, sourceSet)
val sourceSetModuleName = GradleProjectResolverUtil.resolveSourceSetModuleName(context, storage, projectModel, externalProject, sourceSet.name)
val sourceRootData = GradleSourceRootData(externalProject, sourceSet, contentRootPaths, sourceSetModuleName, entitySource)
storage addEntity createModuleEntity(context, sourceRootData)
val moduleEntity = createModuleEntity(context, sourceRootData)
GradleSourceRootSyncContributorExtension.EP_NAME.forEachExtensionSafeAsync {
it.configureSourceSetModules(GradleSourceSetSyncContextImpl(
context, buildModel, projectModel, moduleEntity, sourceSet.name
))
}
storage addEntity moduleEntity
}
}
}
Expand Down Expand Up @@ -213,4 +222,12 @@ internal class GradleSourceRootSyncContributor : GradleSyncContributor {
override val projectPath: String,
override val phase: GradleSyncPhase,
) : GradleBridgeEntitySource

private data class GradleSourceSetSyncContextImpl(
override val resolverContext: ProjectResolverContext,
override val buildModel: GradleLightBuild,
override val projectModel: GradleLightProject,
override val moduleEntity: ModuleEntityBuilder,
override val sourceSetName: String
) : GradleSourceSetSyncContext
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.service.syncContributor

import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.platform.workspace.jps.entities.ModuleEntityBuilder
import com.intellij.platform.workspace.storage.MutableEntityStorage
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.model.ExternalSourceSet
import org.jetbrains.plugins.gradle.model.GradleLightBuild
import org.jetbrains.plugins.gradle.model.GradleLightProject
import org.jetbrains.plugins.gradle.service.project.ProjectResolverContext

@ApiStatus.NonExtendable
interface GradleSourceSetSyncContext {
val resolverContext: ProjectResolverContext
val buildModel: GradleLightBuild
val projectModel: GradleLightProject
val moduleEntity: ModuleEntityBuilder
val sourceSetName: String
}

interface GradleSourceRootSyncContributorExtension {
suspend fun configureSourceSetModules(context: GradleSourceSetSyncContext)

companion object {
@JvmField
val EP_NAME: ExtensionPointName<GradleSourceRootSyncContributorExtension> = ExtensionPointName.create("org.jetbrains.plugins.gradle.sourceRootSyncContributor")
}
}
3 changes: 3 additions & 0 deletions plugins/gradle/plugin-resources/intellij.gradle.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<extensionPoint qualifiedName="org.jetbrains.plugins.gradle.syncContributor"
interface="org.jetbrains.plugins.gradle.service.syncAction.GradleSyncContributor"
dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.plugins.gradle.sourceRootSyncContributor"
interface="org.jetbrains.plugins.gradle.service.syncContributor.GradleSourceRootSyncContributorExtension"
dynamic="true"/>
<extensionPoint qualifiedName="org.jetbrains.plugins.gradle.syncExtension"
interface="org.jetbrains.plugins.gradle.service.syncAction.GradleSyncExtension"
dynamic="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.intellij.gradle.toolingExtension.impl.model.buildScriptClasspathModel.GradleBuildScriptClasspathModelProvider;
import com.intellij.gradle.toolingExtension.impl.model.projectModel.GradleExternalProjectModelProvider;
import com.intellij.gradle.toolingExtension.impl.model.sourceSetDependencyModel.GradleSourceSetDependencyModelProvider;
import com.intellij.gradle.toolingExtension.impl.model.sourceSetDependencyModel.GradleSourceSetDependencyPolicyModelProvider;
import com.intellij.gradle.toolingExtension.impl.model.sourceSetModel.GradleSourceSetModelProvider;
import com.intellij.gradle.toolingExtension.impl.model.taskModel.GradleTaskModelProvider;
import com.intellij.gradle.toolingExtension.util.GradleVersionUtil;
Expand Down Expand Up @@ -795,6 +796,7 @@ private static boolean isSimpleTaskNameAllowed(@NotNull GradleModuleData gradleM
super.getModelProviders(),
new GradleSourceSetModelProvider(),
new GradleSourceSetDependencyModelProvider(),
new GradleSourceSetDependencyPolicyModelProvider(),
new GradleExternalProjectModelProvider(),
new GradleTaskModelProvider(),
new GradleBuildScriptClasspathModelProvider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ sealed interface GradleModelFetchPhase : Comparable<GradleModelFetchPhase>, Seri
@JvmField
val PROJECT_MODEL_PHASE: GradleModelFetchPhase = BuildFinished(0, "PROJECT_MODEL_PHASE")

/**
* In this phase, Gradle model providers fetch the Gradle dependency download policy. This phase influences the behavior of other model
* builders, but doesn't provide any models itself.
*/
@JvmField
@ApiStatus.Internal
val DEPENDENCY_DOWNLOAD_POLICY_PHASE: GradleModelFetchPhase = BuildFinished(500, "DEPENDENCY_DOWNLOAD_POLICY_PHASE")

/**
* In this phase, Gradle model providers fetch a Gradle project source set models.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public void populateModels(
@NotNull Collection<? extends GradleBuild> buildModels,
@NotNull GradleModelConsumer modelConsumer
) {
GradleModelProviderUtil.buildModelsRecursively(controller, buildModels, GradleDependencyDownloadPolicy.class, GradleModelConsumer.NOOP);
GradleModelProviderUtil.buildModels(controller, buildModels, GradleSourceSetArtifactBuildRequest.class, GradleModelConsumer.NOOP);
GradleModelProviderUtil.buildModels(controller, buildModels, GradleSourceSetDependencyModel.class, modelConsumer);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.gradle.toolingExtension.impl.model.sourceSetDependencyModel;

import com.intellij.gradle.toolingExtension.impl.model.dependencyDownloadPolicyModel.GradleDependencyDownloadPolicy;
import com.intellij.gradle.toolingExtension.impl.model.sourceSetArtifactIndex.GradleSourceSetArtifactBuildRequest;
import com.intellij.gradle.toolingExtension.impl.util.GradleModelProviderUtil;
import com.intellij.gradle.toolingExtension.modelAction.GradleModelFetchPhase;

import org.gradle.tooling.BuildController;
import org.gradle.tooling.model.gradle.GradleBuild;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.GradleSourceSetDependencyModel;
import org.jetbrains.plugins.gradle.model.ProjectImportModelProvider;

import java.util.Collection;

@ApiStatus.Internal
public class GradleSourceSetDependencyPolicyModelProvider implements ProjectImportModelProvider {

@Override
public GradleModelFetchPhase getPhase() {
return GradleModelFetchPhase.DEPENDENCY_DOWNLOAD_POLICY_PHASE;
}

@Override
public void populateModels(
@NotNull BuildController controller,
@NotNull Collection<? extends GradleBuild> buildModels,
@NotNull GradleModelConsumer modelConsumer
) {
GradleModelProviderUtil.buildModelsRecursively(controller, buildModels, GradleDependencyDownloadPolicy.class, GradleModelConsumer.NOOP);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,6 @@ fun applyCompilerArgumentsToFacetSettings(
) {
with(kotlinFacetSettings) {
updateCompilerArguments {


val oldPluginOptions = this.pluginOptions
val emptyArgs = this::class.java.getDeclaredConstructor().newInstance()

Expand All @@ -200,73 +198,78 @@ fun applyCompilerArgumentsToFacetSettings(
if (modelsProvider != null && module != null)
module.configureSdkIfPossible(this, modelsProvider)

val allFacetFields = this.kotlinFacetFields.allFields

val ignoredFields = hashSetOf(
K2JVMCompilerArguments::noJdk.name,
K2JVMCompilerArguments::jdkHome.name,
)

val ignoredAsAdditionalArguments = ignoredFields + hashSetOf(
CommonCompilerArguments::fragments.name,
CommonCompilerArguments::fragmentRefines.name,
CommonCompilerArguments::fragmentSources.name,

K2JVMCompilerArguments::moduleName.name,
K2JVMCompilerArguments::noReflect.name,
K2JVMCompilerArguments::noStdlib.name,
K2JVMCompilerArguments::allowNoSourceFiles.name,
K2JVMCompilerArguments::jvmDefault.name,
K2JVMCompilerArguments::reportPerf.name,

K2NativeCompilerArguments::enableAssertions.name,
K2NativeCompilerArguments::debug.name,
K2NativeCompilerArguments::outputName.name,
K2NativeCompilerArguments::linkerArguments.name,
K2NativeCompilerArguments::singleLinkerArguments.name,
K2NativeCompilerArguments::produce.name,
K2NativeCompilerArguments::target.name,
K2NativeCompilerArguments::shortModuleName.name,
K2NativeCompilerArguments::noendorsedlibs.name,

K2JSCompilerArguments::outputFile.name,

K2JSCompilerArguments::outputDir.name,
K2JSCompilerArguments::moduleName.name,
)

fun exposeAsAdditionalArgument(property: KProperty1<CommonCompilerArguments, Any?>) =
/* Handled by facet directly */
property.name !in allFacetFields &&
/* Explicitly not shown to users as 'additional arguments' */
property.name !in ignoredAsAdditionalArguments &&
/* Default value from compiler arguments is used */
property.get(this) != property.get(emptyArgs)


val additionalArgumentsString = with(this::class.java.getDeclaredConstructor().newInstance()) {
copyFieldsSatisfying(this@updateCompilerArguments, this) { exposeAsAdditionalArgument(it) }
val internalArguments = internalArguments.map(ManualLanguageFeatureSetting::stringRepresentation).toSet()
freeArgs = freeArgs.filterNot { it in internalArguments }
toArgumentStrings().joinToString(separator = " ") {
if (StringUtil.containsWhitespaces(it) || it.startsWith('"')) {
StringUtil.wrapWithDoubleQuote(StringUtil.escapeQuotes(it))
} else it
}
}
updateCompilerSettings(this, emptyArgs)
}
}
}

fun IKotlinFacetSettings.updateCompilerSettings(
args: CommonCompilerArguments, emptyArgs: CommonCompilerArguments = args::class.java.getDeclaredConstructor().newInstance()
) {

compilerSettings?.additionalArguments = additionalArgumentsString.ifEmpty { CompilerSettings.DEFAULT_ADDITIONAL_ARGUMENTS }
val allFacetFields = args.kotlinFacetFields.allFields

/* 'Reset' ignored fields and arguments that will be exposed as 'additional arguments' to the user */
with(this::class.java.getDeclaredConstructor().newInstance()) {
copyFieldsSatisfying(this, this@updateCompilerArguments) { exposeAsAdditionalArgument(it) || it.name in ignoredFields }
}
fun exposeAsAdditionalArgument(property: KProperty1<CommonCompilerArguments, Any?>) =/* Handled by facet directly */
property.name !in allFacetFields &&/* Explicitly not shown to users as 'additional arguments' */
property.name !in ignoredAsAdditionalArguments &&/* Default value from compiler arguments is used */
property.get(args) != property.get(emptyArgs)

updateMergedArguments()

val additionalArgumentsString = with(args::class.java.getDeclaredConstructor().newInstance()) {
copyFieldsSatisfying(args, this) { exposeAsAdditionalArgument(it) }
val internalArguments = internalArguments.map(ManualLanguageFeatureSetting::stringRepresentation).toSet()
freeArgs = freeArgs.filterNot { it in internalArguments }
toArgumentStrings().joinToString(separator = " ") {
if (StringUtil.containsWhitespaces(it) || it.startsWith('"')) {
StringUtil.wrapWithDoubleQuote(StringUtil.escapeQuotes(it))
} else it
}
}

if (compilerSettings == null) compilerSettings = CompilerSettings()
compilerSettings?.additionalArguments = additionalArgumentsString.ifEmpty { CompilerSettings.DEFAULT_ADDITIONAL_ARGUMENTS }

/* 'Reset' ignored fields and arguments that will be exposed as 'additional arguments' to the user */
with(args::class.java.getDeclaredConstructor().newInstance()) {
copyFieldsSatisfying(this, args) { exposeAsAdditionalArgument(it) || it.name in ignoredFields }
}

updateMergedArguments()
}

private val ignoredFields = hashSetOf(
K2JVMCompilerArguments::noJdk.name,
K2JVMCompilerArguments::jdkHome.name,
)

private val ignoredAsAdditionalArguments = ignoredFields + hashSetOf(
CommonCompilerArguments::fragments.name,
CommonCompilerArguments::fragmentRefines.name,
CommonCompilerArguments::fragmentSources.name,

K2JVMCompilerArguments::moduleName.name,
K2JVMCompilerArguments::noReflect.name,
K2JVMCompilerArguments::noStdlib.name,
K2JVMCompilerArguments::allowNoSourceFiles.name,
K2JVMCompilerArguments::jvmDefault.name,
K2JVMCompilerArguments::reportPerf.name,

K2NativeCompilerArguments::enableAssertions.name,
K2NativeCompilerArguments::debug.name,
K2NativeCompilerArguments::outputName.name,
K2NativeCompilerArguments::linkerArguments.name,
K2NativeCompilerArguments::singleLinkerArguments.name,
K2NativeCompilerArguments::produce.name,
K2NativeCompilerArguments::target.name,
K2NativeCompilerArguments::shortModuleName.name,
K2NativeCompilerArguments::noendorsedlibs.name,

K2JSCompilerArguments::outputFile.name,

K2JSCompilerArguments::outputDir.name,
K2JSCompilerArguments::moduleName.name,
)

private fun Module.configureSdkIfPossible(compilerArguments: CommonCompilerArguments, modelsProvider: IdeModifiableModelsProvider) {
// SDK for Android module is already configured by Android plugin at this point
if (isAndroidModule(modelsProvider) || shouldSkipSdkConfiguration(compilerArguments)) return
Expand Down
Loading