performane improvement: quickly find artifact by source file

This commit is contained in:
nik
2009-11-18 10:33:19 +03:00
parent 5c456c2e38
commit eda225b7af
6 changed files with 159 additions and 19 deletions
@@ -0,0 +1,35 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author nik
*/
public abstract class ArtifactBySourceFileFinder {
public static ArtifactBySourceFileFinder getInstance(@NotNull Project project) {
return ServiceManager.getService(project, ArtifactBySourceFileFinder.class);
}
public abstract Collection<? extends Artifact> findArtifacts(@NotNull VirtualFile sourceFile);
}
@@ -0,0 +1,104 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.packaging.impl.artifacts;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.packaging.elements.ComplexPackagingElementType;
import com.intellij.packaging.elements.PackagingElementFactory;
import com.intellij.packaging.impl.elements.FileOrDirectoryCopyPackagingElement;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* @author nik
*/
public class ArtifactBySourceFileFinderImpl extends ArtifactBySourceFileFinder {
private CachedValue<MultiValuesMap<VirtualFile, Artifact>> myFile2Artifacts;
private final Project myProject;
public ArtifactBySourceFileFinderImpl(Project project) {
myProject = project;
}
public CachedValue<MultiValuesMap<VirtualFile, Artifact>> getFileToArtifactsMap() {
if (myFile2Artifacts == null) {
myFile2Artifacts =
CachedValuesManager.getManager(myProject).createCachedValue(new CachedValueProvider<MultiValuesMap<VirtualFile, Artifact>>() {
public Result<MultiValuesMap<VirtualFile, Artifact>> compute() {
MultiValuesMap<VirtualFile, Artifact> result = computeFileToArtifactsMap();
List<ModificationTracker> trackers = new ArrayList<ModificationTracker>();
trackers.add(ArtifactManager.getInstance(myProject).getModificationTracker());
for (ComplexPackagingElementType<?> type : PackagingElementFactory.getInstance().getComplexElementTypes()) {
ContainerUtil.addIfNotNull(type.getAllSubstitutionsModificationTracker(myProject), trackers);
}
return Result.create(result, trackers.toArray(new ModificationTracker[trackers.size()]));
}
}, false);
}
return myFile2Artifacts;
}
private MultiValuesMap<VirtualFile, Artifact> computeFileToArtifactsMap() {
final MultiValuesMap<VirtualFile, Artifact> result = new MultiValuesMap<VirtualFile, Artifact>();
final ArtifactManager artifactManager = ArtifactManager.getInstance(myProject);
for (final Artifact artifact : artifactManager.getArtifacts()) {
ArtifactUtil.processFileOrDirectoryCopyElements(artifact, new PackagingElementProcessor<FileOrDirectoryCopyPackagingElement<?>>() {
@Override
public boolean process(@NotNull FileOrDirectoryCopyPackagingElement<?> element, @NotNull PackagingElementPath path) {
final VirtualFile root = element.findFile();
if (root != null) {
result.put(root, artifact);
}
return true;
}
}, artifactManager.getResolvingContext(), true);
}
return result;
}
@Override
public Collection<? extends Artifact> findArtifacts(@NotNull VirtualFile sourceFile) {
final MultiValuesMap<VirtualFile, Artifact> map = getFileToArtifactsMap().getValue();
if (map.isEmpty()) {
return Collections.emptyList();
}
List<Artifact> result = null;
VirtualFile file = sourceFile;
while (file != null) {
final Collection<Artifact> artifacts = map.get(file);
if (artifacts != null) {
if (result == null) {
result = new SmartList<Artifact>();
}
result.addAll(artifacts);
}
file = file.getParent();
}
return result != null ? result : Collections.<Artifact>emptyList();
}
}
@@ -294,15 +294,6 @@ public class ArtifactUtil {
});
}
public static Collection<? extends Artifact> findArtifactsByFile(@NotNull final VirtualFile file, @NotNull Project project) {
final Collection<Trinity<Artifact, PackagingElementPath, String>> items = findContainingArtifactsWithOutputPaths(file, project);
final List<Artifact> result = new ArrayList<Artifact>();
for (Trinity<Artifact, PackagingElementPath, String> item : items) {
result.add(item.getFirst());
}
return result;
}
public static void processFileOrDirectoryCopyElements(Artifact artifact,
PackagingElementProcessor<FileOrDirectoryCopyPackagingElement<?>> processor,
PackagingElementResolvingContext context,
@@ -15,11 +15,10 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -36,16 +35,17 @@ public class PackageFileAction extends AnAction {
boolean visible = false;
final Project project = e.getData(PlatformDataKeys.PROJECT);
if (project != null) {
final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
if (files != null && files.length > 0) {
final List<VirtualFile> files = getFilesToPackage(e, project);
if (!files.isEmpty()) {
visible = true;
e.getPresentation().setText(files.length == 1 ? CompilerBundle.message("action.name.package.file") : CompilerBundle.message("action.name.package.files"));
e.getPresentation().setText(files.size() == 1 ? CompilerBundle.message("action.name.package.file") : CompilerBundle.message("action.name.package.files"));
}
}
e.getPresentation().setVisible(visible);
}
@NotNull
private static List<VirtualFile> getFilesToPackage(@NotNull AnActionEvent e, @NotNull Project project) {
final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY);
if (files == null) return Collections.emptyList();
@@ -58,7 +58,7 @@ public class PackageFileAction extends AnAction {
fileIndex.isInSourceContent(file) && compilerManager.isCompilableFileType(file.getFileType())) {
return Collections.emptyList();
}
final Collection<? extends Artifact> artifacts = ArtifactUtil.findArtifactsByFile(file, project);
final Collection<? extends Artifact> artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file);
for (Artifact artifact : artifacts) {
if (!StringUtil.isEmpty(artifact.getOutputPath())) {
result.add(file);
@@ -80,22 +80,22 @@ public class PackageFileAction extends AnAction {
for (VirtualFile file : files) {
PackageFileWorker.packageFile(file, project);
}
setStatusText(project, VfsUtil.toVirtualFileArray(files));
setStatusText(project, files);
}
catch (IOException e) {
Messages.showErrorDialog(CompilerBundle.message("message.tect.package.file.io.error", e), CommonBundle.getErrorTitle());
}
}
public static void setStatusText(Project project, VirtualFile[] files) {
if (files.length != 0) {
private static void setStatusText(Project project, List<VirtualFile> files) {
if (!files.isEmpty()) {
String fileNames = "";
for (VirtualFile file : files) {
if (fileNames.length() != 0) fileNames += ", ";
fileNames+="'"+file.getName()+"'";
}
String time = DateFormat.getTimeInstance().format(new Date());
final String statusText = CompilerBundle.message("status.text.file.has.been.packaged", files.length, fileNames, time);
final String statusText = CompilerBundle.message("status.text.file.has.been.packaged", files.size(), fileNames, time);
WindowManager.getInstance().getStatusBar(project).setInfo(statusText);
}
}
@@ -16,8 +16,11 @@
package com.intellij.packaging.elements;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.ModificationTracker;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author nik
@@ -28,4 +31,9 @@ public abstract class ComplexPackagingElementType<E extends ComplexPackagingElem
}
public abstract String getShowContentActionText();
@Nullable
public ModificationTracker getAllSubstitutionsModificationTracker(@NotNull Project project) {
return null;
}
}
+2
View File
@@ -348,6 +348,8 @@
serviceImplementation="com.intellij.packaging.impl.artifacts.ArtifactManagerImpl"/>
<projectService serviceInterface="com.intellij.packaging.artifacts.ArtifactPointerManager"
serviceImplementation="com.intellij.packaging.impl.artifacts.ArtifactPointerManagerImpl"/>
<projectService serviceInterface="com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder"
serviceImplementation="com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinderImpl"/>
<applicationService serviceInterface="com.intellij.conversion.ConversionService"
serviceImplementation="com.intellij.conversion.impl.ConversionServiceImpl"/>