Skip to content

Commit d198b02

Browse files
committed
Breaking down updateProjectModel method
1 parent f4903ff commit d198b02

File tree

3 files changed

+156
-104
lines changed

3 files changed

+156
-104
lines changed

base/src/com/google/idea/blaze/base/qsync/ProjectUpdater.java

+13-99
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
*/
1616
package com.google.idea.blaze.base.qsync;
1717

18-
import com.google.common.collect.ImmutableList;
18+
import static com.google.common.collect.ImmutableSet.toImmutableSet;
19+
1920
import com.google.common.collect.ImmutableMap;
2021
import com.google.common.collect.ImmutableSet;
2122
import com.google.common.collect.Sets;
@@ -35,36 +36,20 @@
3536
import com.google.idea.blaze.qsync.project.ProjectProto.LibrarySource;
3637
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
3738
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager;
38-
import com.intellij.openapi.module.Module;
3939
import com.intellij.openapi.module.ModuleType;
4040
import com.intellij.openapi.module.ModuleTypeManager;
4141
import com.intellij.openapi.project.Project;
42-
import com.intellij.openapi.roots.ContentEntry;
43-
import com.intellij.openapi.roots.DependencyScope;
44-
import com.intellij.openapi.roots.LibraryOrderEntry;
45-
import com.intellij.openapi.roots.ModifiableRootModel;
46-
import com.intellij.openapi.roots.OrderEntry;
4742
import com.intellij.openapi.roots.OrderRootType;
48-
import com.intellij.openapi.roots.SourceFolder;
4943
import com.intellij.openapi.roots.libraries.Library;
5044
import com.intellij.openapi.roots.libraries.Library.ModifiableModel;
5145
import com.intellij.openapi.vfs.VfsUtil;
52-
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
53-
import org.jetbrains.jps.model.java.JavaSourceRootType;
54-
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
55-
5646
import java.io.File;
5747
import java.nio.file.Path;
5848
import java.nio.file.Paths;
59-
import java.util.AbstractMap;
6049
import java.util.List;
6150
import java.util.Set;
6251
import java.util.function.Function;
6352

64-
import static com.google.common.collect.ImmutableList.toImmutableList;
65-
import static com.google.common.collect.ImmutableSet.toImmutableSet;
66-
import static java.util.Arrays.stream;
67-
6853
/**
6954
* An object that monitors the build graph and applies the changes to the project structure.
7055
*/
@@ -141,74 +126,9 @@ private void updateProjectModel(ProjectProto.Project spec, Context<?> context) {
141126
libMapBuilder.put(libSpec.getName(), library);
142127
}
143128
ImmutableMap<String, Library> libMap = libMapBuilder.buildOrThrow();
144-
145-
List<AbstractMap.SimpleImmutableEntry<Module, ProjectProto.Module>> modules =
146-
spec.getModulesList().stream().map(moduleSpec -> {
147-
Module module =
148-
models.newModule(
149-
imlDirectory.toPath().resolve(moduleSpec.getName() + ".iml").toString(),
150-
mapModuleType(moduleSpec.getType()).getId());
151-
152-
ModifiableRootModel roots = models.getModifiableRootModel(module);
153-
ImmutableList<OrderEntry> existingLibraryOrderEntries =
154-
stream(roots.getOrderEntries())
155-
.filter(it -> it instanceof LibraryOrderEntry)
156-
.collect(toImmutableList());
157-
for (OrderEntry entry : existingLibraryOrderEntries) {
158-
roots.removeOrderEntry(entry);
159-
}
160-
// TODO: should this be encapsulated in ProjectProto.Module?
161-
roots.inheritSdk();
162-
163-
// TODO instead of removing all content entries and re-adding, we should calculate the
164-
// diff.
165-
for (ContentEntry entry : roots.getContentEntries()) {
166-
roots.removeContentEntry(entry);
167-
}
168-
for (ProjectProto.ContentEntry ceSpec : moduleSpec.getContentEntriesList()) {
169-
ProjectPath projectPath = ProjectPath.create(ceSpec.getRoot());
170-
171-
ContentEntry contentEntry =
172-
roots.addContentEntry(
173-
UrlUtil.pathToUrl(projectPathResolver.resolve(projectPath).toString()));
174-
for (ProjectProto.SourceFolder sfSpec : ceSpec.getSourcesList()) {
175-
ProjectPath sourceFolderProjectPath = ProjectPath.create(sfSpec.getProjectPath());
176-
177-
JavaSourceRootProperties properties =
178-
JpsJavaExtensionService.getInstance()
179-
.createSourceRootProperties(
180-
sfSpec.getPackagePrefix(), sfSpec.getIsGenerated());
181-
JavaSourceRootType rootType =
182-
sfSpec.getIsTest() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
183-
String url =
184-
UrlUtil.pathToUrl(
185-
projectPathResolver.resolve(sourceFolderProjectPath).toString(),
186-
sourceFolderProjectPath.innerJarPath());
187-
SourceFolder unused = contentEntry.addSourceFolder(url, rootType, properties);
188-
}
189-
for (String exclude : ceSpec.getExcludesList()) {
190-
contentEntry.addExcludeFolder(
191-
UrlUtil.pathToIdeaDirectoryUrl(workspaceRoot.absolutePathFor(exclude)));
192-
}
193-
}
194-
195-
for (String lib : moduleSpec.getLibraryNameList()) {
196-
Library library = libMap.get(lib);
197-
if (library == null) {
198-
throw new IllegalStateException(
199-
"Module refers to library " + lib + " not present in the project spec");
200-
}
201-
LibraryOrderEntry entry = roots.addLibraryEntry(library);
202-
// TODO should this stuff be specified by the Module proto too?
203-
entry.setScope(DependencyScope.COMPILE);
204-
entry.setExported(false);
205-
}
206-
return new AbstractMap.SimpleImmutableEntry<>(module, moduleSpec);
207-
}).toList();
208-
return new AbstractMap.SimpleImmutableEntry<>(models, modules);
129+
return ProjectUpdaterHelper.getModulesForModels(spec, models, imlDirectory, projectPathResolver, workspaceRoot, libMap);
209130
},
210-
readValue -> {
211-
IdeModifiableModelsProvider models = readValue.getKey();
131+
(models, modules) -> {
212132
WorkspaceLanguageSettings workspaceLanguageSettings =
213133
LanguageSupport.createWorkspaceLanguageSettings(projectViewSet);
214134

@@ -217,21 +137,15 @@ private void updateProjectModel(ProjectProto.Project spec, Context<?> context) {
217137
// suitable
218138
// data type to be passed in here instead of androidResourceDirectories and
219139
// androidSourcePackages
220-
for (AbstractMap.SimpleImmutableEntry<Module, ProjectProto.Module> moduleEntry : readValue.getValue()) {
221-
ProjectProto.Module moduleSpec = moduleEntry.getValue();
222-
syncPlugin.updateProjectStructureForQuerySync(
223-
project,
224-
context,
225-
models,
226-
workspaceRoot,
227-
moduleEntry.getKey(),
228-
ImmutableSet.copyOf(moduleSpec.getAndroidResourceDirectoriesList()),
229-
ImmutableSet.<String>builder()
230-
.addAll(moduleSpec.getAndroidSourcePackagesList())
231-
.addAll(moduleSpec.getAndroidCustomPackagesList())
232-
.build(),
233-
workspaceLanguageSettings);
234-
}
140+
ProjectUpdaterHelper.updateProjectStructureForQuerySync(
141+
project,
142+
context,
143+
models,
144+
modules,
145+
workspaceRoot,
146+
workspaceLanguageSettings,
147+
syncPlugin
148+
);
235149
}
236150
models.commit();
237151
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package com.google.idea.blaze.base.qsync
2+
3+
import com.google.common.collect.ImmutableMap
4+
import com.google.common.collect.ImmutableSet
5+
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot
6+
import com.google.idea.blaze.base.sync.projectview.WorkspaceLanguageSettings
7+
import com.google.idea.blaze.base.util.UrlUtil
8+
import com.google.idea.blaze.common.Context
9+
import com.google.idea.blaze.qsync.project.ProjectPath
10+
import com.google.idea.blaze.qsync.project.ProjectProto
11+
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
12+
import com.intellij.openapi.module.Module
13+
import com.intellij.openapi.module.ModuleType
14+
import com.intellij.openapi.module.ModuleTypeManager
15+
import com.intellij.openapi.project.Project
16+
import com.intellij.openapi.roots.DependencyScope
17+
import com.intellij.openapi.roots.LibraryOrderEntry
18+
import com.intellij.openapi.roots.libraries.Library
19+
import org.jetbrains.jps.model.java.JavaSourceRootProperties
20+
import org.jetbrains.jps.model.java.JavaSourceRootType
21+
import org.jetbrains.jps.model.java.JpsJavaExtensionService
22+
import java.io.File
23+
24+
object ProjectUpdaterHelper {
25+
26+
private fun mapModuleType(type: ProjectProto.ModuleType): ModuleType<*> =
27+
when (type) {
28+
ProjectProto.ModuleType.MODULE_TYPE_DEFAULT -> ModuleTypeManager.getInstance().defaultModuleType
29+
ProjectProto.ModuleType.UNRECOGNIZED -> throw IllegalStateException("Unrecognised module type $type")
30+
}
31+
32+
private fun getModuleForModuleSpec(
33+
moduleSpec: ProjectProto.Module,
34+
modelsProvider: IdeModifiableModelsProvider,
35+
imlDirectory: File,
36+
projectPathResolver: ProjectPath.Resolver,
37+
workspaceRoot: WorkspaceRoot,
38+
libMap: Map<String, Library>,
39+
): Module {
40+
val module = modelsProvider.newModule(
41+
imlDirectory.toPath().resolve(moduleSpec.getName() + ".iml").toString(),
42+
mapModuleType(moduleSpec.type).id
43+
)
44+
val roots = modelsProvider.getModifiableRootModel(module)
45+
roots.orderEntries
46+
.filterIsInstance(LibraryOrderEntry::class.java)
47+
.forEach(roots::removeOrderEntry)
48+
49+
// TODO: should this be encapsulated in ProjectProto.Module?
50+
roots.inheritSdk();
51+
// TODO instead of removing all content entries and re-adding, we should calculate the diff.
52+
roots.contentEntries.forEach(roots::removeContentEntry);
53+
54+
for (ceSpec in moduleSpec.contentEntriesList) {
55+
val projectPath = ProjectPath.create(ceSpec.root)
56+
val contentEntry = roots.addContentEntry(
57+
UrlUtil.pathToUrl(
58+
projectPathResolver.resolve(projectPath).toString()
59+
)
60+
)
61+
for (sfSpec in ceSpec.sourcesList) {
62+
val sourceFolderProjectPath = ProjectPath.create(sfSpec.projectPath)
63+
val properties =
64+
JpsJavaExtensionService.getInstance().createSourceRootProperties(
65+
sfSpec.packagePrefix,
66+
sfSpec.isGenerated
67+
)
68+
val rootType = if (sfSpec.isTest) JavaSourceRootType.TEST_SOURCE else JavaSourceRootType.SOURCE
69+
val url =
70+
UrlUtil.pathToUrl(
71+
projectPathResolver.resolve(sourceFolderProjectPath).toString(),
72+
sourceFolderProjectPath.innerJarPath()
73+
)
74+
75+
contentEntry.addSourceFolder<JavaSourceRootProperties?>(url, rootType, properties)
76+
}
77+
for (exclude in ceSpec.excludesList) {
78+
contentEntry.addExcludeFolder(
79+
UrlUtil.pathToIdeaDirectoryUrl(workspaceRoot.absolutePathFor(exclude))
80+
)
81+
}
82+
}
83+
84+
moduleSpec.libraryNameList.forEach { lib ->
85+
val library = libMap[lib]
86+
?: throw IllegalStateException("Module refers to library $lib not present in the project spec")
87+
roots.addLibraryEntry(library).apply {
88+
// TODO should this stuff be specified by the Module proto too?
89+
setScope(DependencyScope.COMPILE)
90+
setExported(false)
91+
}
92+
}
93+
return module
94+
}
95+
96+
@JvmStatic
97+
fun getModulesForModels(
98+
spec: ProjectProto.Project,
99+
models: IdeModifiableModelsProvider,
100+
imlDirectory: File,
101+
projectPathResolver: ProjectPath.Resolver,
102+
workspaceRoot: WorkspaceRoot,
103+
libMap: ImmutableMap<String, Library>
104+
): Pair<IdeModifiableModelsProvider, List<Pair<Module, ProjectProto.Module>>> {
105+
val modules = spec.modulesList.map { moduleSpec ->
106+
val module = getModuleForModuleSpec(moduleSpec, models, imlDirectory, projectPathResolver, workspaceRoot, libMap)
107+
module to moduleSpec
108+
}
109+
return models to modules
110+
}
111+
112+
@JvmStatic
113+
fun updateProjectStructureForQuerySync(
114+
project: Project,
115+
context: Context<*>,
116+
models: IdeModifiableModelsProvider,
117+
modules: List<Pair<Module, ProjectProto.Module>>,
118+
workspaceRoot: WorkspaceRoot,
119+
workspaceLanguageSettings: WorkspaceLanguageSettings,
120+
syncPlugin: BlazeQuerySyncPlugin
121+
) {
122+
for ((module, moduleSpec) in modules) {
123+
syncPlugin.updateProjectStructureForQuerySync(
124+
project,
125+
context,
126+
models,
127+
workspaceRoot,
128+
module,
129+
ImmutableSet.copyOf(moduleSpec.getAndroidResourceDirectoriesList()),
130+
ImmutableSet.Builder<String>()
131+
.addAll(moduleSpec.androidSourcePackagesList)
132+
.addAll(moduleSpec.androidCustomPackagesList)
133+
.build(),
134+
workspaceLanguageSettings
135+
)
136+
}
137+
}
138+
}

base/src/com/google/idea/blaze/base/qsync/ProjectUpdaterThreadingUtils.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,20 @@ import com.intellij.openapi.application.writeAction
2020
import com.intellij.openapi.diagnostic.Logger
2121
import kotlinx.coroutines.runBlocking
2222
import java.util.concurrent.Callable
23-
import java.util.function.Consumer
23+
import java.util.function.BiConsumer
2424

2525
class ProjectUpdaterThreadingUtils {
2626
companion object {
2727
val logger = Logger.getInstance(ProjectUpdaterThreadingUtils::class.java)
2828

2929
@JvmStatic
30-
fun <T> readWriteAction(readPart: Callable<T>, commit: Consumer<T>) {
30+
fun <T, U> readWriteAction(readPart: Callable<Pair<T, U>>, commit: BiConsumer<T, U>) {
3131
runBlocking {
3232
readAndWriteAction {
3333
logger.info("Starting read operation")
34-
val ret = readPart.call();
34+
val (t, u) = readPart.call();
3535
writeAction {
36-
commit.accept(ret)
36+
commit.accept(t, u)
3737
}
3838
}
3939
}
@@ -42,7 +42,7 @@ class ProjectUpdaterThreadingUtils {
4242
@JvmStatic
4343
fun performWriteAction(action: Runnable) {
4444
runBlocking {
45-
writeAction<Unit> {
45+
writeAction {
4646
action.run()
4747
}
4848
}

0 commit comments

Comments
 (0)