/******************************************************************************* * Copyright (c) 2014, 2015 Google Inc and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Glassmyer <jogl@google.com> - import group sorting is broken - https://bugs.eclipse.org/430303 * Lars Vogel <Lars.Vogel@vogella.com> - 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<String> typeConflicts; final Set<String> staticConflicts; Conflicts(Set<String> typeConflicts, Set<String> 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<String> implicitImportContainers; ConflictIdentifier( OnDemandComputer onDemandComputer, TypeConflictingSimpleNameFinder typeConflictFinder, StaticConflictingSimpleNameFinder staticConflictFinder, Set<String> 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<ImportName> imports, Set<ImportName> addedImports, Set<String> typeExplicitSimpleNames, Set<String> staticExplicitSimpleNames, IProgressMonitor progressMonitor) throws JavaModelException { Collection<OnDemandReduction> onDemandCandidates = this.onDemandComputer.identifyPossibleReductions( imports, addedImports, typeExplicitSimpleNames, staticExplicitSimpleNames); Set<String> typeOnDemandContainers = new HashSet<>(extractContainerNames(onDemandCandidates, false)); Set<String> 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<String> typeConflicts = findConflictingSimpleNames( this.typeConflictFinder, imports, false, typeOnDemandContainers, progressMonitor); Set<String> staticConflicts = findConflictingSimpleNames( this.staticConflictFinder, imports, true, staticOnDemandContainers, progressMonitor); return new Conflicts(typeConflicts, staticConflicts); } private Collection<String> extractContainerNames( Collection<OnDemandReduction> onDemandCandidates, boolean isStatic) { Collection<String> 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<String> extractOnDemandContainerNames( Collection<ImportName> imports, boolean isStatic) { Collection<String> onDemandContainerNames = new ArrayList<>(imports.size()); for (ImportName importName : imports) { if (importName.isOnDemand() && importName.isStatic == isStatic) { onDemandContainerNames.add(importName.containerName); } } return onDemandContainerNames; } private Set<String> findConflictingSimpleNames( ConflictingSimpleNameFinder conflictFinder, Set<ImportName> imports, boolean isStatic, Set<String> onDemandImportedContainers, IProgressMonitor monitor) throws JavaModelException { if (onDemandImportedContainers.isEmpty() || imports.isEmpty()) { return Collections.emptySet(); } Set<String> simpleNames = new HashSet<>(); for (ImportName currentImport : imports) { if (currentImport.isStatic == isStatic) { simpleNames.add(currentImport.simpleName); } } return conflictFinder.findConflictingSimpleNames(simpleNames, onDemandImportedContainers, monitor); } }