/** * Determine if a file is currently referenced by any part of any project in the workspace. * * @param fileSpecification An {@link IFileSpecification} that can be used to get the name of the * file to check. * @return true if the specified file is referenced by any part of any project in the workspace, * false otherwise. */ @SuppressWarnings("unused") private boolean isKnownFile(IFileSpecification fileSpecification) { // make sure that nobody is calling isKnownFile outside of an assert if (!assertionsEnabled) throw new RuntimeException("isKnownFile() should only ever be called from an assert"); // paths passed into this function need to have been normalized assert (fileSpecification .getPath() .equals(FilenameNormalization.normalize(fileSpecification.getPath()))) : "Path not normalized"; Collection<WeakReference<ICompilationUnit>> relatedCompilationUnits = pathToCompilationUnitMapping.get(fileSpecification.getPath()); return (relatedCompilationUnits != null) && (relatedCompilationUnits.size() > 0); }
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()); } }
private final Collection<ICompilationUnit> collectAssociatedCompilationUnits( IFileSpecification file) { String filename = file.getPath(); Collection<WeakReference<ICompilationUnit>> relatedCompilationUnits = pathToCompilationUnitMapping.getVisibleAndInvisible(filename); // relatedCompilationUnits should never be null, but it is OK for it to be empty, as // we can be null, if someone passes us in a arbitrary file which has no compilation // units associated with it. assert (relatedCompilationUnits != null) : "relatedCompilationUnits should never be null"; // add any compilation units which include the file, as they need to be recompiled also Collection<WeakReference<ICompilationUnit>> includingCompilationUnits = includeFilesToIncludingCompilationUnitMapping.get(filename); Collection<WeakReference<ICompilationUnit>> allRelatedCompilationUnits = new HashSet<WeakReference<ICompilationUnit>>(); allRelatedCompilationUnits.addAll(relatedCompilationUnits); allRelatedCompilationUnits.addAll(includingCompilationUnits); HashSet<ICompilationUnit> associatedCompilationUnits = new HashSet<ICompilationUnit>(); for (WeakReference<ICompilationUnit> relatedCURef : allRelatedCompilationUnits) { ICompilationUnit relatedCU = relatedCURef.get(); if (relatedCU != null) { associatedCompilationUnits.add(relatedCU); } } final Set<ICompilationUnit> associatedCompilationUnitsAccountingForConflictingDefinitions = ASProjectScope.getCompilationUnitsWithConflictingDefinitions( this, associatedCompilationUnits); return associatedCompilationUnitsAccountingForConflictingDefinitions; }
@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); } }
@Override public void fileChanged(IFileSpecification changedFile) { // paths passed into this function need to have been normalized assert (changedFile.getPath().equals(FilenameNormalization.normalize(changedFile.getPath()))) : "Path not normalized"; Map<ICompilerProject, Set<ICompilationUnit>> cusToUpdate = new HashMap<ICompilerProject, Set<ICompilationUnit>>(); startIdleState(); try { Collection<ICompilationUnit> relatedCompilationUnits = collectAssociatedCompilationUnits(changedFile); HashSet<ICompilationUnit> compilationUnitsToInvalidate = new HashSet<ICompilationUnit>(); compilationUnitsToInvalidate.addAll(relatedCompilationUnits); invalidate(changedFile, relatedCompilationUnits, cusToUpdate); pathToFileSpecMap.put(changedFile.getPath(), changedFile); } finally { endIdleState(cusToUpdate); } }
@Override public void fileAdded(IFileSpecification addedFile) { // paths passed into this function need to have been normalized assert (addedFile.getPath().equals(FilenameNormalization.normalize(addedFile.getPath()))) : "Path not normalized"; Map<ICompilerProject, Set<ICompilationUnit>> cusToUpdate = new HashMap<ICompilerProject, Set<ICompilationUnit>>(); startIdleState(); try { // It would be nice to be able to assert that the file being added // is not a known file, but this is not currently possible. When builder project // settings are changed in ways such as adding a new source path, there are two notifications, // 1) The project has changed and Configurator.applyToProject() is called which adds any new // files to the workspace. // 2) eclipse then sends file adds on a file which we know about because of 1). // Until the notification is straightened out, we can't have this assert. This just means // that // we're potentially doing a slightly more costly invalidation when fileAdded() is called // instead // of fileChanged(), but as this only really happens when project settings are changed, it // shouldn't // be a real performance hit. // assert (!isKnownFile(addedFile)); String path = addedFile.getPath(); pathToFileSpecMap.put(path, addedFile); getSWCManager().remove(new File(path)); File f = new File(path); CompilerProject[] projects = getProjects(); boolean compilationUnitAdded = false; for (CompilerProject project : projects) { compilationUnitAdded = project.handleAddedFile(f) || compilationUnitAdded; if (project instanceof ASProject) compilationUnitAdded = ((ASProject) project).invalidateLibraries(Collections.singleton(f)) || compilationUnitAdded; } Set<ICompilationUnit> compilationUnitsToInvalidate = new HashSet<ICompilationUnit>(); if (compilationUnitAdded) { // we now have compilation units from the newly added file, get it's // name, and see if there's either: // - any unresolved dependencies which could be resolved by this new name // - any compilation units which depend on the new name, and could now have // an ambiguous reference Collection<ICompilationUnit> relatedCompilationUnits = collectAssociatedCompilationUnits(addedFile); compilationUnitsToInvalidate.addAll(relatedCompilationUnits); compilationUnitsToInvalidate.addAll( getCompilationUnitsDependingOnMissingDefinitions(relatedCompilationUnits)); } // even if no compilation units were added, the added file may be a missing file which was // a source for an embed, so need to invalidate any CUs which have a dependency on the missing // filename for (CompilerProject project : projects) { compilationUnitsToInvalidate.addAll( project.getDependenciesOnUnfoundReferencedSourceFile(addedFile.getPath())); } invalidate(addedFile, compilationUnitsToInvalidate, cusToUpdate); } finally { endIdleState(cusToUpdate); } }