private final void invalidate( IFileSpecification fileSpec, Collection<ICompilationUnit> compilationUnits, Map<ICompilerProject, Set<ICompilationUnit>> cusToUpdate) { mxmlDataManager.invalidate(fileSpec); // Tell the SWC manager the SWC file is invalid. getSWCManager().remove(new File(fileSpec.getPath())); if (compilationUnits.size() == 0) return; Set<ICompilationUnit> unitsToInvalidate = new HashSet<ICompilationUnit>(); unitsToInvalidate.addAll(compilationUnits); Set<ICompilationUnit> unitsToClean = Sets.<ICompilationUnit>union( DependencyGraph.computeInvalidationSet(unitsToInvalidate), getCompilationUnitsDependingOnMissingDefinitions(unitsToInvalidate)); notifyInvalidationListener(unitsToClean); // Do the actual invalidation Map<ICompilerProject, Set<File>> invalidatedSWCFiles = new HashMap<ICompilerProject, Set<File>>(); for (ICompilationUnit compilationUnit : unitsToClean) { boolean clearCUFileScope = unitsToInvalidate.contains(compilationUnit); compilationUnit.clean(invalidatedSWCFiles, cusToUpdate, clearCUFileScope); } // invalidate any library files in the project for (Map.Entry<ICompilerProject, Set<File>> e : invalidatedSWCFiles.entrySet()) { if (e.getKey() instanceof IASProject) ((IASProject) e.getKey()).invalidateLibraries(e.getValue()); } }
/** * Maintain a mapping between filenames and compilation units. Needed for incremental compilation. */ public void addCompilationUnit(ICompilationUnit compilationUnit) { String path = compilationUnit.getAbsoluteFilename(); // paths passed into this function need to have been normalized assert (path.equals(FilenameNormalization.normalize(path))) : "Path not normalized"; pathToCompilationUnitMapping.add(path, compilationUnit); }
@Override public void fileRemoved(IFileSpecification removedFile) { // paths passed into this function need to have been normalized assert (removedFile.getPath().equals(FilenameNormalization.normalize(removedFile.getPath()))) : "Path not normalized"; final String path = removedFile.getPath(); final Set<ASProject> affectedProjects = new HashSet<ASProject>(); Map<ICompilerProject, Set<ICompilationUnit>> cusToUpdate = new HashMap<ICompilerProject, Set<ICompilationUnit>>(); Collection<ICompilationUnit> relatedCompilationUnits = Collections.emptyList(); startIdleState(); try { relatedCompilationUnits = collectAssociatedCompilationUnits(removedFile); // collect the affected projects before invalidating the relatedCompilationUnits, as removed // compilation units will have their projects null'd out during invalidate, causing an NPE. for (ICompilationUnit compilationUnit : relatedCompilationUnits) { if (compilationUnit == null) continue; ICompilerProject containingProject = compilationUnit.getProject(); assert (containingProject instanceof ASProject); affectedProjects.add((ASProject) containingProject); } invalidate(removedFile, relatedCompilationUnits, cusToUpdate); } finally { File f = new File(path); for (ASProject project : affectedProjects) { project.removeSourceFile(f); } // update the pathToCompilationUnitMapping CU by CU, rather than // just taking the whole path away, as we don't want to loose mappings // between SWC compilation units and the SWC path for (ICompilationUnit cu : relatedCompilationUnits) { if (cu.getCompilationUnitType() != UnitType.SWC_UNIT) { pathToCompilationUnitMapping.remove(path, cu); includeFilesToIncludingCompilationUnitMapping.remove(path, cu); } } pathToFileSpecMap.remove(path); endIdleState(cusToUpdate); } }
/** * Gets the {@link IFileSpecification} for the root source file of the specified {@link * ICompilationUnit}. * * @param compilationUnit A compilation unit. * @return Tthe {@link IFileSpecification} for the root source file of the specified {@link * ICompilationUnit} */ public IFileSpecification getFileSpecificationForCompilationUnit( ICompilationUnit compilationUnit) { String path = compilationUnit.getAbsoluteFilename(); // paths passed into this function need to have been normalized assert (path.equals(FilenameNormalization.normalize(path))) : "Path not normalized"; // Make sure that we seen this path associated with a compilation unit before. assert pathToCompilationUnitMapping.get(path) != null; return getFileSpecification(path); }
private static Collection<ICompilationUnit> getInvisibleCompilationUnits( final StringToCompilationUnitMap compilationUnitMap, final String sortKey, ICompilerProject project) { Collection<WeakReference<ICompilationUnit>> compilationUnitRefs = compilationUnitMap.getInvisible(sortKey, project); ArrayList<ICompilationUnit> compilationUnits = new ArrayList<ICompilationUnit>(compilationUnitRefs.size()); for (WeakReference<ICompilationUnit> cuRef : compilationUnitRefs) { final ICompilationUnit cu = cuRef.get(); // Nothing in the compiler pins the invisible compilation units // so we have to check that the weak reference is still good. if (cu != null) { assert cu.isInvisible() : "StringToCompilationUnitMap.getInvisible returned a visible compilation unit."; compilationUnits.add(cu); } } return compilationUnits; }
private Set<ICompilationUnit> getCompilationUnitsDependingOnMissingDefinitions( Collection<ICompilationUnit> addedUnits) { Set<ICompilationUnit> compilationUnitsToInvalidate = new HashSet<ICompilationUnit>(); for (ICompilationUnit addedCompilationUnit : addedUnits) { try { CompilerProject project = (CompilerProject) addedCompilationUnit.getProject(); List<String> newIdentifierNames = addedCompilationUnit.getShortNames(); for (String newIdentifierName : newIdentifierNames) { compilationUnitsToInvalidate.addAll( project.getDependenciesOnUnfoundDefinition(newIdentifierName)); compilationUnitsToInvalidate.addAll( project.getDependenciesOnDefinition(newIdentifierName)); } } catch (InterruptedException e) { // should never happen, as all threads should be stopped e.printStackTrace(); } } return compilationUnitsToInvalidate; }
/** * Remove a compilation unit from the filename to compilation unit map * * @param compilationUnit The compilation unit to be removed. */ public void removeCompilationUnit(ICompilationUnit compilationUnit) { String path = compilationUnit.getAbsoluteFilename(); // paths passed into this function need to have been normalized assert (path.equals(FilenameNormalization.normalize(path))) : "Path not normalized"; pathToCompilationUnitMapping.remove(path, compilationUnit); ((CompilationUnitBase) compilationUnit).clearIncludedFilesFromWorkspace(); // only remove the file spec if there are no more remaining CUs tied // to that path if (pathToCompilationUnitMapping.get(path).isEmpty() && includeFilesToIncludingCompilationUnitMapping.get(path).isEmpty()) { pathToFileSpecMap.remove(path); } }
/** * When an ISWC has changed in memory, invalidate any compilation units which depend on the units * which depend on the SWC * * @param unitsRemoved The collection of compilation units to be removed. * @param unitsAdded The collection compilation units to be added. */ public void swcChanged( Collection<ICompilationUnit> unitsRemoved, Collection<ICompilationUnit> unitsAdded, Runnable runWhileIdle) { final Map<ICompilerProject, Set<ICompilationUnit>> cusToUpdate = new HashMap<ICompilerProject, Set<ICompilationUnit>>(); final Set<ICompilationUnit> unitsRemoveSet = ImmutableSet.copyOf(unitsRemoved); startIdleState(); try { // Find all the compilation units reference a definition with the same base // name as a definition defined by any of the compilation units in the SWC that is // changing. final Collection<ICompilationUnit> unitsDependingOnMissingDefinitions = getCompilationUnitsDependingOnMissingDefinitions(unitsAdded); // Compute the set of compilation units to invalidate by starting with the union of // the unitsDependingOnMissingDefinitions and the list of // compilation units we are removing. Set<ICompilationUnit> unitsToInvalidate = DependencyGraph.computeInvalidationSet( Iterables.concat(unitsRemoved, unitsDependingOnMissingDefinitions)); notifyInvalidationListener(unitsToInvalidate); // Do the actual invalidation Map<ICompilerProject, Set<File>> invalidatedSWCFiles = new HashMap<ICompilerProject, Set<File>>(); for (ICompilationUnit compilationUnit : unitsToInvalidate) { compilationUnit.clean( invalidatedSWCFiles, cusToUpdate, unitsRemoveSet.contains(compilationUnit)); } runWhileIdle.run(); } finally { endIdleState(cusToUpdate); } }
private void notifyInvalidationListener(Collection<ICompilationUnit> unitsToClean) { if (invalidationListeners.isEmpty()) return; Map<ICompilerProject, Collection<InvalidatedDefinition>> invalidationMap = new HashMap<ICompilerProject, Collection<InvalidatedDefinition>>(); for (ICompilationUnit compilationUnit : unitsToClean) { // Collect all definitions associated with the compilation unit Collection<IDefinition> definitions = compilationUnit.getDefinitionPromises(); if (definitions.size() == 0) { // no definition promises, so getting the file scope should be cheap. try { IFileScopeRequestResult fsr = compilationUnit.getFileScopeRequest().get(); definitions = fsr.getExternallyVisibleDefinitions(); } catch (InterruptedException e1) { assert false : "Since this is a single threaded method, we should never be interrupted"; } } // for all the found definition, build up a map of projects to a list of // InvalidatedDefinitions // and pass this map onto the registered invalidation listener to do with what it will if (definitions.size() > 0) { Collection<InvalidatedDefinition> invalidatedDefinitions = invalidationMap.get(compilationUnit.getProject()); if (invalidatedDefinitions == null) { invalidatedDefinitions = new LinkedList<InvalidatedDefinition>(); invalidationMap.put(compilationUnit.getProject(), invalidatedDefinitions); } String filename = compilationUnit.getAbsoluteFilename(); for (IDefinition definition : definitions) { String qName = definition.getQualifiedName(); InvalidatedDefinition invalidatedDefinition = new InvalidatedDefinition(qName, filename); invalidatedDefinitions.add(invalidatedDefinition); } } } for (IInvalidationListener listener : invalidationListeners) listener.definitionsChanged(invalidationMap); }