use of com.google.idea.blaze.base.filecache.ArtifactState in project intellij by bazelbuild.
the class BlazeIdeInterfaceAspectsImpl method updateState.
@Nullable
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());
// 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;
}
use of com.google.idea.blaze.base.filecache.ArtifactState in project intellij by bazelbuild.
the class BlazeIdeInterfaceState method fromProto.
public static BlazeIdeInterfaceState fromProto(ProjectData.BlazeIdeInterfaceState proto) {
ImmutableMap<String, TargetKey> targets = ProtoWrapper.map(proto.getFileToTargetMap(), ArtifactState::migrateOldKeyFormat, TargetKey::fromProto);
ImmutableMap.Builder<String, ArtifactState> artifacts = ImmutableMap.builder();
for (LocalFileOrOutputArtifact output : proto.getIdeInfoFilesList()) {
ArtifactState state = ArtifactStateProtoConverter.fromProto(output);
if (state == null) {
continue;
}
artifacts.put(state.getKey(), state);
}
return new BlazeIdeInterfaceState(artifacts.build(), ImmutableBiMap.copyOf(targets));
}
use of com.google.idea.blaze.base.filecache.ArtifactState in project intellij by bazelbuild.
the class PackageManifestReader method readPackageManifestFiles.
/**
* @return A map from java source absolute file path to declared package string.
*/
public Map<TargetKey, Map<ArtifactLocation, String>> readPackageManifestFiles(Project project, BlazeContext context, ArtifactLocationDecoder decoder, Map<TargetKey, ArtifactLocation> javaPackageManifests, ListeningExecutorService executorService) {
Map<OutputArtifact, TargetKey> fileToLabelMap = Maps.newHashMap();
for (Map.Entry<TargetKey, ArtifactLocation> entry : javaPackageManifests.entrySet()) {
TargetKey key = entry.getKey();
BlazeArtifact artifact = decoder.resolveOutput(entry.getValue());
if (artifact instanceof OutputArtifact) {
fileToLabelMap.put((OutputArtifact) artifact, key);
}
}
ArtifactsDiff diff;
try {
diff = ArtifactsDiff.diffArtifacts(artifactState, fileToLabelMap.keySet());
artifactState = diff.getNewState();
} catch (InterruptedException e) {
throw new ProcessCanceledException(e);
} catch (ExecutionException e) {
context.setHasError();
IssueOutput.error("Updating package manifest files failed: " + e).submit(context);
throw new AssertionError("Unhandled exception", e);
}
// Find all not cached {@link RemoteOutputArtifact} and download them before parsing manifest
// file
ImmutableList.Builder<RemoteOutputArtifact> toDownload = ImmutableList.builder();
for (OutputArtifact outputArtifact : diff.getUpdatedOutputs()) {
if (!(outputArtifact instanceof RemoteOutputArtifact)) {
continue;
}
if (findArtifactInCache(project, outputArtifact) != null) {
continue;
}
toDownload.add((RemoteOutputArtifact) outputArtifact);
}
ListenableFuture<?> fetchRemoteArtifactFuture = RemoteArtifactPrefetcher.getInstance().downloadArtifacts(project.getName(), toDownload.build());
ListenableFuture<?> fetchFuture = PrefetchService.getInstance().prefetchFiles(BlazeArtifact.getLocalFiles(diff.getUpdatedOutputs()), true, false);
if (!FutureUtil.waitForFuture(context, Futures.allAsList(fetchRemoteArtifactFuture, fetchFuture)).timed("FetchPackageManifests", EventType.Prefetching).withProgressMessage("Reading package manifests...").run().success()) {
return null;
}
List<ListenableFuture<Void>> futures = Lists.newArrayList();
for (OutputArtifact file : diff.getUpdatedOutputs()) {
futures.add(executorService.submit(() -> {
Map<ArtifactLocation, String> manifest = parseManifestFile(project, file);
manifestMap.put(fileToLabelMap.get(file), manifest);
return null;
}));
}
for (ArtifactState file : diff.getRemovedOutputs()) {
TargetKey key = this.fileToLabelMap.get(file);
if (key != null) {
manifestMap.remove(key);
}
}
this.fileToLabelMap = fileToLabelMap.entrySet().stream().filter(e -> diff.getNewState().containsKey(e.getKey().getKey())).collect(toImmutableMap(e -> e.getKey().toArtifactState(), Map.Entry::getValue));
try {
Futures.allAsList(futures).get();
} catch (ExecutionException | InterruptedException e) {
logger.error(e);
throw new IllegalStateException("Could not read sources");
}
return manifestMap;
}
use of com.google.idea.blaze.base.filecache.ArtifactState in project intellij by bazelbuild.
the class EmptyJarTracker method fromProto.
public static EmptyJarTracker fromProto(ProjectData.EmptyJarTracker proto) {
if (proto.getEntriesCount() == 0) {
return EmptyJarTracker.builder().build();
}
Builder emptyJarTrackerBuilder = builder();
for (ProjectData.EmptyJarTracker.Entry entry : proto.getEntriesList()) {
ArtifactState artifactState = ArtifactStateProtoConverter.fromProto(entry.getArtifact());
if (artifactState == null) {
continue;
}
emptyJarTrackerBuilder.addEntry(artifactState, entry.getIsEmpty());
}
return emptyJarTrackerBuilder.build();
}
use of com.google.idea.blaze.base.filecache.ArtifactState in project intellij by bazelbuild.
the class EmptyLibrary method doRemoveEmptyLibraries.
private static ImmutableMap<LibraryKey, BlazeJarLibrary> doRemoveEmptyLibraries(Project project, BlazeContext context, ArtifactLocationDecoder locationDecoder, Map<LibraryKey, BlazeJarLibrary> allLibraries, EmptyJarTracker oldProjectData, BlazeJavaImportResult.Builder importResultBuilder) {
long startTime = System.currentTimeMillis();
Set<OutputArtifact> currentOutputArtifacts = new HashSet<>();
Map<LibraryKey, ArtifactState> libraryKeyToArtifactState = new HashMap<>();
// `OutputArtifact` does not have an associated `ArtifactState`
for (Map.Entry<LibraryKey, BlazeJarLibrary> entry : allLibraries.entrySet()) {
ArtifactLocation libraryJar = entry.getValue().libraryArtifact.jarForIntellijLibrary();
BlazeArtifact libraryArtifact = locationDecoder.resolveOutput(libraryJar);
if (libraryArtifact instanceof OutputArtifact) {
ArtifactState libraryArtifactState = ((OutputArtifact) libraryArtifact).toArtifactState();
libraryKeyToArtifactState.put(entry.getKey(), libraryArtifactState);
currentOutputArtifacts.add((OutputArtifact) libraryArtifact);
}
}
// Update emptyJarTracker by reevaluating any artifact that might have changed since last sync
EmptyJarTracker emptyJarTracker = getUpdatedEmptyJarTracker(project, context, currentOutputArtifacts, oldProjectData);
// Put non-empty artifacts in `result`
Map<LibraryKey, BlazeJarLibrary> result = new LinkedHashMap<>();
for (Map.Entry<LibraryKey, BlazeJarLibrary> entry : allLibraries.entrySet()) {
ArtifactState libraryArtifactState = libraryKeyToArtifactState.get(entry.getKey());
if (libraryArtifactState == null || !emptyJarTracker.isKnownEmpty(libraryArtifactState)) {
result.put(entry.getKey(), entry.getValue());
}
}
context.output(PrintOutput.log(String.format("Filtered %d JARs, in %dms", allLibraries.size() - result.size(), System.currentTimeMillis() - startTime)));
importResultBuilder.setEmptyJarTracker(emptyJarTracker);
return ImmutableMap.copyOf(result);
}
Aggregations