in base/src/com/google/idea/blaze/base/sync/aspects/BlazeIdeInterfaceAspectsImpl.java [288:447]
private static TargetMapAndInterfaceState updateState(
Project project,
BlazeContext parentContext,
@Nullable BlazeIdeInterfaceState prevState,
ArtifactsDiff fileState,
BlazeConfigurationHandler configHandler,
BlazeVersionData versionData,
WorkspaceLanguageSettings languageSettings,
ImportRoots importRoots,
boolean mergeWithOldState,
@Nullable TargetMap oldTargetMap) {
AspectStrategy aspectStrategy = AspectStrategy.getInstance(versionData);
Result<TargetMapAndInterfaceState> result =
Scope.push(
parentContext,
context -> {
context.push(new TimingScope("UpdateTargetMap", EventType.Other));
context.output(new StatusOutput("Updating target map..."));
// ideally, we'd flush through a per-build sync time parsed from BEP. For now, though
// just set an approximate, batched sync time.
Instant syncTime = Instant.now();
Map<String, ArtifactState> nextFileState = new HashMap<>(fileState.getNewState());
// If we're not removing we have to merge the old state
// into the new one or we'll miss file removes next time
if (mergeWithOldState && prevState != null) {
prevState.ideInfoFileState.forEach(nextFileState::putIfAbsent);
}
BlazeIdeInterfaceState.Builder state = BlazeIdeInterfaceState.builder();
state.ideInfoFileState = ImmutableMap.copyOf(nextFileState);
Map<TargetKey, TargetIdeInfo> targetMap = Maps.newHashMap();
if (prevState != null && oldTargetMap != null) {
targetMap.putAll(oldTargetMap.map());
state.ideInfoToTargetKey.putAll(prevState.ideInfoFileToTargetKey);
}
// Update removed unless we're merging with the old state
if (!mergeWithOldState) {
for (ArtifactState removed : fileState.getRemovedOutputs()) {
TargetKey key = state.ideInfoToTargetKey.remove(removed.getKey());
if (key != null) {
targetMap.remove(key);
}
}
}
AtomicLong totalSizeLoaded = new AtomicLong(0);
Set<LanguageClass> ignoredLanguages = Sets.newConcurrentHashSet();
ListeningExecutorService executor = BlazeExecutor.getInstance().getExecutor();
// Read protos from any new files
List<ListenableFuture<TargetFilePair>> futures = Lists.newArrayList();
for (OutputArtifact file : fileState.getUpdatedOutputs()) {
futures.add(
executor.submit(
() -> {
totalSizeLoaded.addAndGet(file.getLength());
IntellijIdeInfo.TargetIdeInfo message =
aspectStrategy.readAspectFile(file);
TargetIdeInfo target =
protoToTarget(
languageSettings,
importRoots,
message,
ignoredLanguages,
syncTime);
return new TargetFilePair(file, target);
}));
}
Set<TargetKey> newTargets = new HashSet<>();
Set<String> configurations = new LinkedHashSet<>();
configurations.add(configHandler.defaultConfigurationPathComponent);
// Update state with result from proto files
int duplicateTargetLabels = 0;
try {
for (TargetFilePair targetFilePair : Futures.allAsList(futures).get()) {
if (targetFilePair.target != null) {
OutputArtifact file = targetFilePair.file;
String config = file.getConfigurationMnemonic();
configurations.add(config);
TargetKey key = targetFilePair.target.getKey();
if (targetMap.putIfAbsent(key, targetFilePair.target) == null) {
state.ideInfoToTargetKey.forcePut(file.getKey(), key);
} else {
if (!newTargets.add(key)) {
duplicateTargetLabels++;
}
// prioritize the default configuration over build order
if (Objects.equals(config, configHandler.defaultConfigurationPathComponent)) {
targetMap.put(key, targetFilePair.target);
state.ideInfoToTargetKey.forcePut(file.getKey(), key);
}
}
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Result.error(null);
} catch (ExecutionException e) {
return Result.error(e);
}
context.output(
PrintOutput.log(
String.format(
"Loaded %d aspect files, total size %dkB",
fileState.getUpdatedOutputs().size(), totalSizeLoaded.get() / 1024)));
if (duplicateTargetLabels > 0) {
context.output(
new PerformanceWarning(
String.format(
"There were %d duplicate rules, built with the following "
+ "configurations: %s.\nYour IDE sync is slowed down by ~%d%%.",
duplicateTargetLabels,
configurations,
(100 * duplicateTargetLabels / targetMap.size()))));
}
// remove previously synced targets which are now unsupported
for (TargetKey key : ImmutableSet.copyOf(state.ideInfoToTargetKey.values())) {
TargetIdeInfo target = targetMap.get(key);
if (target != null
&& shouldIgnoreTarget(
languageSettings, importRoots, target, ignoredLanguages)) {
state.ideInfoToTargetKey.inverse().remove(key);
targetMap.remove(key);
}
}
// update sync time for unchanged targets
for (String artifactKey : fileState.getNewState().keySet()) {
TargetKey targetKey = state.ideInfoToTargetKey.get(artifactKey);
TargetIdeInfo target = targetKey != null ? targetMap.get(targetKey) : null;
if (target != null) {
targetMap.put(targetKey, target.updateSyncTime(syncTime));
}
}
ignoredLanguages.retainAll(
LanguageSupport.availableAdditionalLanguages(
languageSettings.getWorkspaceType()));
warnIgnoredLanguages(project, context, ignoredLanguages);
return Result.of(
new TargetMapAndInterfaceState(
new TargetMap(ImmutableMap.copyOf(targetMap)), state.build()));
});
if (result.error != null) {
logger.error(result.error);
return null;
}
return result.result;
}