package de.ovgu.cide.typing.jdt.organizeimports; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.ImportDeclaration; import cide.gast.IASTNode; import cide.gparser.ParseException; import de.ovgu.cide.ASTColorChangedEvent; import de.ovgu.cide.CIDECorePlugin; import de.ovgu.cide.features.FeatureModelNotFoundException; import de.ovgu.cide.features.IFeature; import de.ovgu.cide.features.source.ColoredSourceFile; import de.ovgu.cide.features.source.ColoredSourceFileIteratorJob; import de.ovgu.cide.features.source.SourceFileColorManager; import de.ovgu.cide.language.jdt.ASTBridge; import de.ovgu.cide.language.jdt.ASTID; import de.ovgu.cide.language.jdt.AstidWrapper; import de.ovgu.cide.language.jdt.JDTParserWrapper; import de.ovgu.cide.typing.jdt.BindingProjectColorCache; import de.ovgu.cide.typing.jdt.checks.resolutions.ASTBindingFinderHelper; public class OrganizeAllImportsJob extends ColoredSourceFileIteratorJob { public OrganizeAllImportsJob(IProject[] project) { super(project, "Organizing imports", "Organizing"); } protected void processSource(ColoredSourceFile source) throws JavaModelException, CoreException { try { organizeImports(source, null); } catch (ParseException e) { e.printStackTrace(); } } /** * sets the colors of all import statements. needs to parse the JDT ast and * then assign colors to every bridged import statement * * there are two ways to determine the colors of the type declarations. * either there is a BandingProjectColorCache when the current typing * context is known, or (if the cache is null) it is looked up manually, * which is slow. consider this a long running process then. * * @param source * @param bindingProjectColorCache * cache or null if cache is not available * @throws ParseException * @throws CoreException */ public static void organizeImports(ColoredSourceFile source, BindingProjectColorCache bindingProjectColorCache) throws ParseException, CoreException { SourceFileColorManager colorManager = source.getColorManager(); colorManager.beginBatch(); Set<IASTNode> changedNodes = new HashSet<IASTNode>(); try { CompilationUnit ast = JDTParserWrapper.parseJavaFile(source .getResource()); for (Object astnode : ast.imports()) { if (astnode instanceof ImportDeclaration) { ImportDeclaration importDeclaration = (ImportDeclaration) astnode; IBinding importBinding = importDeclaration.resolveBinding(); Set<IFeature> importDeclColors = colorManager .getOwnColors(new AstidWrapper(ASTID .id(importDeclaration))); Set<IFeature> targetColors = new HashSet<IFeature>(); if (importBinding instanceof ITypeBinding) { targetColors = getTargetColors( bindingProjectColorCache, (ITypeBinding) importBinding); } if (targetColors.size() != importDeclColors.size() || !targetColors.containsAll(importDeclColors)) { IASTNode c_importDeclaration = ASTBridge .bridge(importDeclaration); for (IFeature color : targetColors) { if (!importDeclColors.contains(color)) { colorManager.addColor(c_importDeclaration, color); } } for (IFeature color : importDeclColors) { if (!targetColors.contains(color)) { colorManager.removeColor(c_importDeclaration, color); } } changedNodes.add(c_importDeclaration); } } } } finally { colorManager.endBatch(); /** * hack: informing only of changed root element when in fact only * few imports have changed. doing this to avoid massive bridging. */ if (!changedNodes.isEmpty()) CIDECorePlugin.getDefault().notifyListeners( new ASTColorChangedEvent(source, changedNodes, source)); } } /** * if the binding cache is available, this is simple, we can just return the * values from the cache. otherwise we have to determine the target file, * parse it, and look up the colors manually * * source must not be null */ private static Set<IFeature> getTargetColors( BindingProjectColorCache bindingProjectColorCache, ITypeBinding typeBinding) { if (bindingProjectColorCache != null) return bindingProjectColorCache.getColors(typeBinding); IASTNode typeDecl = ASTBindingFinderHelper.getTypeDecl(typeBinding); if (typeDecl == null) return Collections.EMPTY_SET; IFile file = (IFile) typeBinding.getJavaElement().getResource(); try { ColoredSourceFile typeSource = ColoredSourceFile .getColoredSourceFile(file); return typeSource.getColorManager().getColors(typeDecl); } catch (FeatureModelNotFoundException e) { e.printStackTrace(); return Collections.EMPTY_SET; } } }