1+ package org.androidstudio.plugin.util
2+
3+ import com.android.tools.idea.gradle.AndroidGradleJavaProjectModelModifier
4+ import com.android.tools.idea.gradle.dsl.api.GradleBuildModel
5+ import com.android.tools.idea.gradle.dsl.api.dependencies.ArtifactDependencySpec
6+ import com.android.tools.idea.gradle.dsl.api.dependencies.CommonConfigurationNames
7+ import com.android.tools.idea.gradle.project.sync.GradleSyncInvoker
8+ import com.android.tools.idea.gradle.project.sync.GradleSyncListener
9+ import com.android.tools.idea.gradle.project.sync.idea.GradleSyncExecutor
10+ import com.android.tools.idea.gradle.util.GradleUtil
11+ import com.android.tools.idea.project.AndroidProjectInfo
12+ import com.android.tools.idea.projectsystem.TestArtifactSearchScopes
13+ import com.google.wireless.android.sdk.stats.GradleSyncStats
14+ import com.intellij.openapi.command.WriteCommandAction
15+ import com.intellij.openapi.command.undo.BasicUndoableAction
16+ import com.intellij.openapi.command.undo.UndoManager
17+ import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager
18+ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
19+ import com.intellij.openapi.module.Module
20+ import com.intellij.openapi.project.Project
21+ import com.intellij.openapi.roots.DependencyScope
22+ import com.intellij.openapi.roots.ExternalLibraryDescriptor
23+ import com.intellij.openapi.vfs.VirtualFile
24+ import com.intellij.util.containers.ContainerUtil
25+ import org.jetbrains.concurrency.AsyncPromise
26+ import org.jetbrains.concurrency.Promise
27+
28+ class UtAndroidGradleJavaProjectModelModifier : AndroidGradleJavaProjectModelModifier () {
29+ override fun addExternalLibraryDependency (
30+ modules : Collection <Module ?>,
31+ descriptor : ExternalLibraryDescriptor ,
32+ scope : DependencyScope
33+ ): Promise <Void ?>? {
34+ val module = ContainerUtil .getFirstItem(modules) ? : return null
35+
36+ if (! isAndroidGradleProject(module.project)) {
37+ return null
38+ }
39+
40+ val dependencySpec = ArtifactDependencySpec .create(descriptor.libraryArtifactId, descriptor.libraryGroupId, descriptor.preferredVersion)
41+ return addExternalLibraryDependency(module, dependencySpec, scope)
42+
43+ }
44+
45+ private fun addExternalLibraryDependency (
46+ module : Module ,
47+ dependencySpec : ArtifactDependencySpec ,
48+ scope : DependencyScope ,
49+ ): Promise <Void ?>? {
50+ val project = module.project
51+ val openedFile = FileEditorManagerEx .getInstanceEx(project).currentFile
52+ val buildModelsToUpdate: MutableList <GradleBuildModel > = ArrayList ()
53+
54+ val buildModel = GradleBuildModel .get(module) ? : return null
55+ val configurationName = getConfigurationName(module, scope, openedFile)
56+ val dependencies = buildModel.dependencies()
57+ dependencies.addArtifact(configurationName, dependencySpec)
58+ buildModelsToUpdate.add(buildModel)
59+
60+ WriteCommandAction .writeCommandAction(project).withName(" Add Gradle Library Dependency" ).run<RuntimeException > {
61+ buildModelsToUpdate.forEach { buildModel -> buildModel.applyChanges() }
62+ registerUndoAction(project)
63+ }
64+
65+ return doAndroidGradleSync(project, GradleSyncStats .Trigger .TRIGGER_MODIFIER_ADD_LIBRARY_DEPENDENCY )
66+ }
67+
68+ private fun getConfigurationName (module : Module , scope : DependencyScope , openedFile : VirtualFile ? ): String =
69+ GradleUtil .mapConfigurationName(
70+ getLegacyConfigurationName(module, scope, openedFile),
71+ GradleUtil .getAndroidGradleModelVersionInUse(module),
72+ false
73+ )
74+
75+ private fun getLegacyConfigurationName (
76+ module : Module ,
77+ scope : DependencyScope ,
78+ openedFile : VirtualFile ?
79+ ): String {
80+ if (! scope.isForProductionCompile) {
81+ val testScopes = TestArtifactSearchScopes .getInstance(module)
82+ if (testScopes != null && openedFile != null ) {
83+ return if (testScopes.isAndroidTestSource(openedFile)) CommonConfigurationNames .ANDROID_TEST_COMPILE else CommonConfigurationNames .TEST_COMPILE
84+ }
85+ }
86+ return CommonConfigurationNames .COMPILE
87+ }
88+
89+ private fun registerUndoAction (project : Project ) {
90+ UndoManager .getInstance(project).undoableActionPerformed(object : BasicUndoableAction () {
91+
92+ override fun undo () {
93+ doAndroidGradleSync(project, GradleSyncStats .Trigger .TRIGGER_MODIFIER_ACTION_UNDONE )
94+
95+ }
96+
97+ override fun redo () {
98+ doAndroidGradleSync(project, GradleSyncStats .Trigger .TRIGGER_MODIFIER_ACTION_REDONE )
99+ }
100+ })
101+ }
102+
103+ private fun isAndroidGradleProject (project : Project ): Boolean = AndroidProjectInfo .getInstance(project).requiresAndroidModel()
104+
105+ private fun doAndroidGradleSync (project : Project , trigger : GradleSyncStats .Trigger ): AsyncPromise <Void ?> {
106+ val promise = AsyncPromise <Void ?>()
107+ val request = GradleSyncInvoker .Request (trigger)
108+ val listener = object : GradleSyncListener {
109+ override fun syncSucceeded (project : Project ) {
110+ promise.setResult(null )
111+ }
112+
113+ override fun syncFailed (project : Project , errorMessage : String ) {
114+ promise.setError(errorMessage)
115+ }
116+ }
117+ GradleSyncExecutor (project).sync(request, listener)
118+
119+ return promise
120+ }
121+ }
0 commit comments