/* * This file is part of the OpenJML project. * Author: David R. Cok */ package org.jmlspecs.openjml; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.tools.JavaFileObject; import org.jmlspecs.annotation.NonNull; import org.jmlspecs.annotation.Nullable; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; public class Dependencies { // FIXME - The computing and handling of dependencies needs reworking. // The map in this class is static, because otherwise the information // is lost from one compilation context to another. However, this way it // keeps accumulating information forever and will hold on to everything else // in the system, and run out of memory. Need a better solution. // OK for command-line tools but not for the api or Eclipse. // /** The key to use to retrieve the instance of this class from the Context object. */ @NonNull public static final Context.Key<Dependencies> dependenciesKey = new Context.Key<Dependencies>(); /** A method that returns the unique instance of this class for the given Context * (creating it if it does not already exist). * * @param context the Context whose JmlSpecs instance is wanted * @return the singleton instance (per Context) of this class */ public static @NonNull Dependencies instance(@NonNull Context context) { Dependencies instance = context.get(dependenciesKey); if (instance == null) { instance = new Dependencies(context); // registers itself } return instance; } /** Creates an instance in association with the given Context * - do not call the constructor * directly. * * @param context The compilation context */ protected Dependencies(@NonNull Context context) { context.put(dependenciesKey, this); // register itself if (dependsOnMap == null) dependsOnMap = new HashMap<JavaFileObject, Set<JavaFileObject>>(); // NOTE: Although you might get away with it, the goal is to have // this class be independent of all the other tools } /** The map holding the set of things that a given object affects. * */ @NonNull static protected Map<JavaFileObject,Set<JavaFileObject>> dependsOnMap = null; /** Record that item a needs to be recompiled if b changes */ public void dependsOn(@NonNull JavaFileObject a, @NonNull JavaFileObject b) { if (Utils.ifSourcesEqual(a, b)) return; Set<JavaFileObject> t = dependsOnMap.get(b); if (t == null) dependsOnMap.put(b, t = new HashSet<JavaFileObject>()); t.add(a); } /** Record that item a needs to be recompiled if anything in array b changes */ public void dependsOn(@NonNull JavaFileObject a, @NonNull JavaFileObject[] b) { for (JavaFileObject bb: b) dependsOn(a,bb); } /** Record that item a needs to be recompiled if anything in array b changes */ public void dependsOn(@NonNull JavaFileObject a, @NonNull List<JavaFileObject> b) { for (JavaFileObject bb: b) dependsOn(a,bb); } /** Record that item a needs to be recompiled if anything in array b changes */ public void dependsOn(@NonNull JavaFileObject a, @NonNull Collection<JavaFileObject> b) { for (JavaFileObject bb: b) dependsOn(a,bb); } /** Returns a Set of items potentially affected if the argument is changed. * A null result is equivalent to an empty set. */ public @Nullable Set<JavaFileObject> getAffected(@NonNull JavaFileObject a) { return dependsOnMap.get(a); } }