org.eclipse.jdt.internal.core.dom.rewrite.imports.ConflictIdentifier Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2014, 2015 Google Inc and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* John Glassmyer - import group sorting is broken - https://bugs.eclipse.org/430303
* Lars Vogel - Contributions for
* Bug 473178
*******************************************************************************/
package org.eclipse.jdt.internal.core.dom.rewrite.imports;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.JavaModelException;
public class ConflictIdentifier {
/**
* Encapsulates those simple names (of type imports and of static imports) which would be
* imported from multiple on-demand or implicit import containers.
*/
static final class Conflicts {
final Set typeConflicts;
final Set staticConflicts;
Conflicts(Set typeConflicts, Set staticConflicts) {
this.typeConflicts = Collections.unmodifiableSet(new HashSet<>(typeConflicts));
this.staticConflicts = Collections.unmodifiableSet(new HashSet<>(staticConflicts));
}
@Override
public String toString() {
return String.format(
"Conflicts(type: %s; static: %s)", this.typeConflicts, this.staticConflicts); //$NON-NLS-1$
}
}
private final OnDemandComputer onDemandComputer;
private final TypeConflictingSimpleNameFinder typeConflictFinder;
private final StaticConflictingSimpleNameFinder staticConflictFinder;
private final Set implicitImportContainers;
ConflictIdentifier(
OnDemandComputer onDemandComputer,
TypeConflictingSimpleNameFinder typeConflictFinder,
StaticConflictingSimpleNameFinder staticConflictFinder,
Set implicitImportContainers) {
this.onDemandComputer = onDemandComputer;
this.typeConflictFinder = typeConflictFinder;
this.staticConflictFinder = staticConflictFinder;
this.implicitImportContainers = implicitImportContainers;
}
/**
* Identifies the simple names (of the elements of {@code imports}) which would be imported from
* multiple on-demand or implicit import containers.
*
* @param imports
* imports whose simple names are to be considered for conflicts
* @param addedImports
* imports which have been added as part of the rewrite (and could therefore trigger
* on-demand reductions; a subset of {@code imports}
* @param typeExplicitSimpleNames
* simple names of types which are already known to require explicit imports
* @param staticExplicitSimpleNames
* simple names of statics which are already known to require explicit imports
* @param progressMonitor
* a progress monitor used to track time spent searching for conflicts
* @return a {@link Conflicts} object encapsulating the found conflicting type and static names
* @throws JavaModelException if an error occurs while searching for declarations
*/
Conflicts identifyConflicts(
Set imports,
Set addedImports,
Set typeExplicitSimpleNames,
Set staticExplicitSimpleNames,
IProgressMonitor progressMonitor) throws JavaModelException {
Collection onDemandCandidates = this.onDemandComputer.identifyPossibleReductions(
imports, addedImports, typeExplicitSimpleNames, staticExplicitSimpleNames);
Set typeOnDemandContainers = new HashSet<>(extractContainerNames(onDemandCandidates, false));
Set staticOnDemandContainers = new HashSet<>(extractContainerNames(onDemandCandidates, true));
if (!typeOnDemandContainers.isEmpty()) {
// Existing on-demands might conflict with new or existing on-demands.
typeOnDemandContainers.addAll(extractOnDemandContainerNames(imports, false));
// Implicitly imported types might conflict with type on-demands.
typeOnDemandContainers.addAll(this.implicitImportContainers);
// Member types imported by static on-demands might conflict with type on-demands.
typeOnDemandContainers.addAll(staticOnDemandContainers);
}
if (!staticOnDemandContainers.isEmpty()) {
// Existing on-demands might conflict with new or existing on-demands.
staticOnDemandContainers.addAll(extractOnDemandContainerNames(imports, true));
}
Set typeConflicts = findConflictingSimpleNames(
this.typeConflictFinder, imports, false, typeOnDemandContainers, progressMonitor);
Set staticConflicts = findConflictingSimpleNames(
this.staticConflictFinder, imports, true, staticOnDemandContainers, progressMonitor);
return new Conflicts(typeConflicts, staticConflicts);
}
private Collection extractContainerNames(
Collection onDemandCandidates, boolean isStatic) {
Collection containerNames = new ArrayList<>(onDemandCandidates.size());
for (OnDemandReduction onDemandCandidate : onDemandCandidates) {
ImportName containerOnDemand = onDemandCandidate.containerOnDemand;
if (containerOnDemand.isStatic == isStatic) {
containerNames.add(containerOnDemand.containerName);
}
}
return containerNames;
}
private Collection extractOnDemandContainerNames(
Collection imports, boolean isStatic) {
Collection onDemandContainerNames = new ArrayList<>(imports.size());
for (ImportName importName : imports) {
if (importName.isOnDemand() && importName.isStatic == isStatic) {
onDemandContainerNames.add(importName.containerName);
}
}
return onDemandContainerNames;
}
private Set findConflictingSimpleNames(
ConflictingSimpleNameFinder conflictFinder,
Set imports,
boolean isStatic,
Set onDemandImportedContainers,
IProgressMonitor monitor) throws JavaModelException {
if (onDemandImportedContainers.isEmpty() || imports.isEmpty()) {
return Collections.emptySet();
}
Set simpleNames = new HashSet<>();
for (ImportName currentImport : imports) {
if (currentImport.isStatic == isStatic) {
simpleNames.add(currentImport.simpleName);
}
}
return conflictFinder.findConflictingSimpleNames(simpleNames, onDemandImportedContainers, monitor);
}
}