use of com.intellij.util.containers.MultiMap in project intellij-community by JetBrains.
the class ImportHelper method prepareOptimizeImportsResult.
@Nullable("null means no need to replace the import list because they are the same")
PsiImportList prepareOptimizeImportsResult(@NotNull final PsiJavaFile file) {
PsiImportList oldList = file.getImportList();
if (oldList == null)
return null;
// Java parser works in a way that comments may be included to the import list, e.g.:
// import a;
// /* comment */
// import b;
// We want to preserve those comments then.
List<PsiElement> nonImports = new ArrayList<>();
// Note: this array may contain "<packageOrClassName>.*" for unresolved imports!
List<Pair<String, Boolean>> names = new ArrayList<>(collectNamesToImport(file, nonImports));
Collections.sort(names, Comparator.comparing(o -> o.getFirst()));
List<Pair<String, Boolean>> resultList = sortItemsAccordingToSettings(names, mySettings);
final Map<String, Boolean> classesOrPackagesToImportOnDemand = new THashMap<>();
collectOnDemandImports(resultList, mySettings, classesOrPackagesToImportOnDemand);
MultiMap<String, String> conflictingMemberNames = new MultiMap<>();
for (Pair<String, Boolean> pair : resultList) {
if (pair.second) {
conflictingMemberNames.putValue(StringUtil.getShortName(pair.first), StringUtil.getPackageName(pair.first));
}
}
for (String methodName : conflictingMemberNames.keySet()) {
Collection<String> collection = conflictingMemberNames.get(methodName);
if (!classesOrPackagesToImportOnDemand.keySet().containsAll(collection)) {
for (String name : collection) {
classesOrPackagesToImportOnDemand.remove(name);
}
}
}
Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand.keySet());
Set<String> toReimport = new THashSet<>();
calcClassesConflictingViaOnDemandImports(file, classesOrPackagesToImportOnDemand, file.getResolveScope(), toReimport);
classesToUseSingle.addAll(toReimport);
try {
StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand.keySet(), classesToUseSingle);
for (PsiElement nonImport : nonImports) {
text.append("\n").append(nonImport.getText());
}
String ext = StdFileTypes.JAVA.getDefaultExtension();
PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject());
final PsiJavaFile dummyFile = (PsiJavaFile) factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text);
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject());
codeStyleManager.reformat(dummyFile);
PsiImportList newImportList = dummyFile.getImportList();
assert newImportList != null : dummyFile.getText();
PsiImportList result = (PsiImportList) newImportList.copy();
if (oldList.isReplaceEquivalent(result))
return null;
if (!nonImports.isEmpty()) {
PsiElement firstPrevious = newImportList.getPrevSibling();
while (firstPrevious != null && firstPrevious.getPrevSibling() != null) {
firstPrevious = firstPrevious.getPrevSibling();
}
for (PsiElement element = firstPrevious; element != null && element != newImportList; element = element.getNextSibling()) {
result.add(element.copy());
}
for (PsiElement element = newImportList.getNextSibling(); element != null; element = element.getNextSibling()) {
result.add(element.copy());
}
}
return result;
} catch (IncorrectOperationException e) {
LOG.error(e);
return null;
}
}
use of com.intellij.util.containers.MultiMap in project intellij-community by JetBrains.
the class MoveInstanceMethodProcessor method preprocessUsages.
protected boolean preprocessUsages(@NotNull Ref<UsageInfo[]> refUsages) {
final UsageInfo[] usages = refUsages.get();
MultiMap<PsiElement, String> conflicts = new MultiMap<>();
final Set<PsiMember> members = new HashSet<>();
members.add(myMethod);
if (myTargetVariable instanceof PsiField)
members.add((PsiMember) myTargetVariable);
if (!myTargetClass.isInterface()) {
RefactoringConflictsUtil.analyzeAccessibilityConflicts(members, myTargetClass, conflicts, myNewVisibility);
} else {
for (final UsageInfo usage : usages) {
if (usage instanceof InheritorUsageInfo) {
RefactoringConflictsUtil.analyzeAccessibilityConflicts(members, ((InheritorUsageInfo) usage).getInheritor(), conflicts, myNewVisibility);
}
}
}
if (myTargetVariable instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter) myTargetVariable;
for (final UsageInfo usageInfo : usages) {
if (usageInfo instanceof MethodCallUsageInfo) {
final PsiElement methodCall = ((MethodCallUsageInfo) usageInfo).getMethodCallExpression();
if (methodCall instanceof PsiMethodCallExpression) {
final PsiExpression[] expressions = ((PsiMethodCallExpression) methodCall).getArgumentList().getExpressions();
final int index = myMethod.getParameterList().getParameterIndex(parameter);
if (index < expressions.length) {
PsiExpression instanceValue = expressions[index];
instanceValue = RefactoringUtil.unparenthesizeExpression(instanceValue);
if (instanceValue instanceof PsiLiteralExpression && ((PsiLiteralExpression) instanceValue).getValue() == null) {
String message = RefactoringBundle.message("0.contains.call.with.null.argument.for.parameter.1", RefactoringUIUtil.getDescription(ConflictsUtil.getContainer(methodCall), true), CommonRefactoringUtil.htmlEmphasize(parameter.getName()));
conflicts.putValue(instanceValue, message);
}
}
} else if (methodCall instanceof PsiMethodReferenceExpression) {
conflicts.putValue(methodCall, "Method reference would be broken after move");
}
}
}
}
try {
ConflictsUtil.checkMethodConflicts(myTargetClass, myMethod, getPatternMethod(), conflicts);
} catch (IncorrectOperationException e) {
}
return showConflicts(conflicts, usages);
}
use of com.intellij.util.containers.MultiMap in project intellij-community by JetBrains.
the class IncProjectBuilder method clearOutputs.
private void clearOutputs(CompileContext context) throws ProjectBuildException {
final long cleanStart = System.currentTimeMillis();
final MultiMap<File, BuildTarget<?>> rootsToDelete = MultiMap.createSet();
final Set<File> allSourceRoots = ContainerUtil.newTroveSet(FileUtil.FILE_HASHING_STRATEGY);
final ProjectDescriptor projectDescriptor = context.getProjectDescriptor();
final List<? extends BuildTarget<?>> allTargets = projectDescriptor.getBuildTargetIndex().getAllTargets();
for (BuildTarget<?> target : allTargets) {
if (target instanceof ModuleBasedTarget) {
for (File file : target.getOutputRoots(context)) {
rootsToDelete.putValue(file, target);
}
} else {
if (context.getScope().isBuildForced(target)) {
clearOutputFilesUninterruptibly(context, target);
}
}
}
final ModuleExcludeIndex moduleIndex = projectDescriptor.getModuleExcludeIndex();
for (BuildTarget<?> target : allTargets) {
for (BuildRootDescriptor descriptor : projectDescriptor.getBuildRootIndex().getTargetRoots(target, context)) {
// excluding from checks roots with generated sources; because it is safe to delete generated stuff
if (!descriptor.isGenerated()) {
File rootFile = descriptor.getRootFile();
//However if a root isn't excluded it means that its content will be shown in 'Project View' and an user can create new files under it so it would be dangerous to clean such roots
if (moduleIndex.isInContent(rootFile)) {
allSourceRoots.add(rootFile);
}
}
}
}
// check that output and source roots are not overlapping
final CompileScope compileScope = context.getScope();
final List<File> filesToDelete = new ArrayList<>();
final Predicate<BuildTarget<?>> forcedBuild = new Predicate<BuildTarget<?>>() {
public boolean apply(BuildTarget<?> input) {
return compileScope.isBuildForced(input);
}
};
for (Map.Entry<File, Collection<BuildTarget<?>>> entry : rootsToDelete.entrySet()) {
context.checkCanceled();
final File outputRoot = entry.getKey();
final Collection<BuildTarget<?>> rootTargets = entry.getValue();
final Applicability applicability = Applicability.calculate(forcedBuild, rootTargets);
if (applicability == Applicability.NONE) {
continue;
}
boolean okToDelete = applicability == Applicability.ALL;
if (okToDelete && !moduleIndex.isExcluded(outputRoot)) {
// so in this case it is safe to delete such root
if (JpsPathUtil.isUnder(allSourceRoots, outputRoot)) {
okToDelete = false;
} else {
final Set<File> _outRoot = ContainerUtil.newTroveSet(FileUtil.FILE_HASHING_STRATEGY, outputRoot);
for (File srcRoot : allSourceRoots) {
if (JpsPathUtil.isUnder(_outRoot, srcRoot)) {
okToDelete = false;
break;
}
}
}
}
if (okToDelete) {
// do not delete output root itself to avoid lots of unnecessary "roots_changed" events in IDEA
final File[] children = outputRoot.listFiles();
if (children != null) {
for (File child : children) {
if (!child.delete()) {
filesToDelete.add(child);
}
}
} else {
// the output root must be file
if (!outputRoot.delete()) {
filesToDelete.add(outputRoot);
}
}
registerTargetsWithClearedOutput(context, rootTargets);
} else {
if (applicability == Applicability.ALL) {
// only warn if unable to delete because of roots intersection
context.processMessage(new CompilerMessage("", BuildMessage.Kind.WARNING, "Output path " + outputRoot.getPath() + " intersects with a source root. Only files that were created by build will be cleaned."));
}
context.processMessage(new ProgressMessage("Cleaning output directories..."));
// clean only those files we are aware of
for (BuildTarget<?> target : rootTargets) {
if (compileScope.isBuildForced(target)) {
clearOutputFilesUninterruptibly(context, target);
}
}
}
}
if (!filesToDelete.isEmpty()) {
context.processMessage(new ProgressMessage("Cleaning output directories..."));
if (SYNC_DELETE) {
for (File file : filesToDelete) {
context.checkCanceled();
FileUtil.delete(file);
}
} else {
myAsyncTasks.add(FileUtil.asyncDelete(filesToDelete));
}
}
LOG.info("Cleaned output directories in " + (System.currentTimeMillis() - cleanStart) + " ms");
}
use of com.intellij.util.containers.MultiMap in project intellij-community by JetBrains.
the class IncArtifactBuilder method build.
@Override
public void build(@NotNull ArtifactBuildTarget target, @NotNull DirtyFilesHolder<ArtifactRootDescriptor, ArtifactBuildTarget> holder, @NotNull BuildOutputConsumer outputConsumer, @NotNull final CompileContext context) throws ProjectBuildException {
JpsArtifact artifact = target.getArtifact();
String outputFilePath = artifact.getOutputFilePath();
if (StringUtil.isEmpty(outputFilePath)) {
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified"));
return;
}
final ProjectDescriptor pd = context.getProjectDescriptor();
final ArtifactSorter sorter = new ArtifactSorter(pd.getModel());
final Map<JpsArtifact, JpsArtifact> selfIncludingNameMap = sorter.getArtifactToSelfIncludingNameMap();
final JpsArtifact selfIncluding = selfIncludingNameMap.get(artifact);
if (selfIncluding != null) {
String name = selfIncluding.equals(artifact) ? "it" : "'" + selfIncluding.getName() + "' artifact";
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "Cannot build '" + artifact.getName() + "' artifact: " + name + " includes itself in the output layout"));
return;
}
try {
final Collection<String> deletedFiles = holder.getRemovedFiles(target);
String messageText = "Building artifact '" + artifact.getName() + "'...";
context.processMessage(new ProgressMessage(messageText));
LOG.debug(messageText);
runArtifactTasks(context, target.getArtifact(), ArtifactBuildTaskProvider.ArtifactBuildPhase.PRE_PROCESSING);
final SourceToOutputMapping srcOutMapping = pd.dataManager.getSourceToOutputMap(target);
final ArtifactOutputToSourceMapping outSrcMapping = pd.dataManager.getStorage(target, ArtifactOutToSourceStorageProvider.INSTANCE);
final TIntObjectHashMap<Set<String>> filesToProcess = new TIntObjectHashMap<>();
final MultiMap<String, String> filesToDelete = new MultiMap<>();
final Set<String> deletedOutputPaths = new THashSet<>(FileUtil.PATH_HASHING_STRATEGY);
for (String sourcePath : deletedFiles) {
final Collection<String> outputPaths = srcOutMapping.getOutputs(sourcePath);
if (outputPaths != null) {
for (String outputPath : outputPaths) {
if (deletedOutputPaths.add(outputPath)) {
collectSourcesCorrespondingToOutput(outputPath, sourcePath, deletedFiles, outSrcMapping, filesToProcess, filesToDelete);
}
}
}
}
final Set<String> changedOutputPaths = new THashSet<>(FileUtil.PATH_HASHING_STRATEGY);
holder.processDirtyFiles(new FileProcessor<ArtifactRootDescriptor, ArtifactBuildTarget>() {
@Override
public boolean apply(ArtifactBuildTarget target, File file, ArtifactRootDescriptor root) throws IOException {
int rootIndex = root.getRootIndex();
String sourcePath = FileUtil.toSystemIndependentName(file.getPath());
addFileToProcess(filesToProcess, rootIndex, sourcePath, deletedFiles);
final Collection<String> outputPaths = srcOutMapping.getOutputs(sourcePath);
if (outputPaths != null) {
for (String outputPath : outputPaths) {
if (changedOutputPaths.add(outputPath)) {
collectSourcesCorrespondingToOutput(outputPath, sourcePath, deletedFiles, outSrcMapping, filesToProcess, filesToDelete);
}
}
}
return true;
}
});
BuildOperations.cleanOutputsCorrespondingToChangedFiles(context, holder);
for (String outputPath : changedOutputPaths) {
outSrcMapping.remove(outputPath);
}
if (filesToDelete.isEmpty() && filesToProcess.isEmpty()) {
return;
}
deleteOutdatedFiles(filesToDelete, context, srcOutMapping, outSrcMapping);
context.checkCanceled();
context.processMessage(new ProgressMessage("Building artifact '" + artifact.getName() + "': copying files..."));
final Set<JarInfo> changedJars = new THashSet<>();
for (ArtifactRootDescriptor descriptor : pd.getBuildRootIndex().getTargetRoots(target, context)) {
context.checkCanceled();
final Set<String> sourcePaths = filesToProcess.get(descriptor.getRootIndex());
if (sourcePaths == null)
continue;
for (String sourcePath : sourcePaths) {
if (!descriptor.getFilter().shouldBeCopied(sourcePath, pd)) {
if (LOG.isDebugEnabled()) {
LOG.debug("File " + sourcePath + " will be skipped because it isn't accepted by filter");
}
continue;
}
DestinationInfo destination = descriptor.getDestinationInfo();
if (destination instanceof ExplodedDestinationInfo) {
descriptor.copyFromRoot(sourcePath, descriptor.getRootIndex(), destination.getOutputPath(), context, outputConsumer, outSrcMapping);
} else {
List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(destination.getOutputFilePath());
if (sources == null || sources.size() > 0 && sources.get(0).getRootIndex() == descriptor.getRootIndex()) {
outSrcMapping.update(destination.getOutputFilePath(), Collections.<ArtifactOutputToSourceMapping.SourcePathAndRootIndex>emptyList());
changedJars.add(((JarDestinationInfo) destination).getJarInfo());
}
}
}
}
context.checkCanceled();
JarsBuilder builder = new JarsBuilder(changedJars, context, outputConsumer, outSrcMapping);
builder.buildJars();
runArtifactTasks(context, artifact, ArtifactBuildTaskProvider.ArtifactBuildPhase.FINISHING_BUILD);
runArtifactTasks(context, artifact, ArtifactBuildTaskProvider.ArtifactBuildPhase.POST_PROCESSING);
} catch (IOException e) {
throw new ProjectBuildException(e);
}
}
use of com.intellij.util.containers.MultiMap in project intellij-community by JetBrains.
the class GutterIconsConfigurable method createComponent.
@Nullable
@Override
public JComponent createComponent() {
ExtensionPoint<LineMarkerProvider> point = Extensions.getRootArea().getExtensionPoint(LineMarkerProviders.EP_NAME);
@SuppressWarnings("unchecked") LanguageExtensionPoint<LineMarkerProvider>[] extensions = (LanguageExtensionPoint<LineMarkerProvider>[]) point.getExtensions();
NullableFunction<LanguageExtensionPoint<LineMarkerProvider>, PluginDescriptor> function = point1 -> {
LineMarkerProvider instance = point1.getInstance();
return instance instanceof LineMarkerProviderDescriptor && ((LineMarkerProviderDescriptor) instance).getName() != null ? point1.getPluginDescriptor() : null;
};
MultiMap<PluginDescriptor, LanguageExtensionPoint<LineMarkerProvider>> map = ContainerUtil.groupBy(Arrays.asList(extensions), function);
Map<GutterIconDescriptor, PluginDescriptor> pluginDescriptorMap = ContainerUtil.newHashMap();
Set<String> ids = new HashSet<>();
myDescriptors = new ArrayList<>();
for (final PluginDescriptor descriptor : map.keySet()) {
Collection<LanguageExtensionPoint<LineMarkerProvider>> points = map.get(descriptor);
for (LanguageExtensionPoint<LineMarkerProvider> extensionPoint : points) {
GutterIconDescriptor instance = (GutterIconDescriptor) extensionPoint.getInstance();
if (instance.getOptions().length > 0) {
for (GutterIconDescriptor option : instance.getOptions()) {
if (ids.add(option.getId())) {
myDescriptors.add(option);
}
pluginDescriptorMap.put(option, descriptor);
}
} else {
if (ids.add(instance.getId())) {
myDescriptors.add(instance);
}
pluginDescriptorMap.put(instance, descriptor);
}
}
}
/*
List<GutterIconDescriptor> options = new ArrayList<GutterIconDescriptor>();
for (Iterator<GutterIconDescriptor> iterator = myDescriptors.iterator(); iterator.hasNext(); ) {
GutterIconDescriptor descriptor = iterator.next();
if (descriptor.getOptions().length > 0) {
options.addAll(Arrays.asList(descriptor.getOptions()));
iterator.remove();
}
}
myDescriptors.addAll(options);
*/
myDescriptors.sort((o1, o2) -> {
if (pluginDescriptorMap.get(o1) != pluginDescriptorMap.get(o2))
return 0;
return Comparing.compare(o1.getName(), o2.getName());
});
PluginDescriptor current = null;
for (GutterIconDescriptor descriptor : myDescriptors) {
PluginDescriptor pluginDescriptor = pluginDescriptorMap.get(descriptor);
if (pluginDescriptor != current) {
myFirstDescriptors.put(descriptor, pluginDescriptor);
current = pluginDescriptor;
}
}
myList.setItems(myDescriptors, GutterIconDescriptor::getName);
myShowGutterIconsJBCheckBox.addChangeListener(e -> myList.setEnabled(myShowGutterIconsJBCheckBox.isSelected()));
return myPanel;
}
Aggregations