namespaces = new HashSet<String>();
final Map<QName, Map<String, Source>> dependents = new HashMap<QName, Map<String, Source>>();
Set<Source> swcSources = swcContext.cachedSources();
Context ascContext = null;
if (perCompileData != null)
{
ascContext = new Context(perCompileData);
}
// put all the Source objects together
final Set<Source> sources = new HashSet<Source>();
{
sources.addAll(swcSources);
if (fileSpec != null)
sources.addAll(fileSpec.sources());
if (sourceList != null)
sources.addAll(sourceList.sources().values());
if (sourcePath != null)
sources.addAll(sourcePath.sources().values());
if (bundlePath != null)
sources.addAll(bundlePath.sources().values());
if (includedClasses != null)
sources.addAll(includedClasses.values());
}
// build a dependency graph
for (Source source : sources)
{
if (source.getName() == null)
{
continue;
}
CompilationUnit u = source.getCompilationUnit();
if (u == null)
{
continue;
}
// collect the names of all the update file includes...
for (Iterator j = source.getUpdatedFileIncludes(); j != null && j.hasNext();)
{
VirtualFile f = (VirtualFile) j.next();
includeUpdated.add(f.getNameForReporting());
}
// register QName --> VirtualFile.getName()
for (QName qName : u.topLevelDefinitions)
{
qNames.put(qName, source);
dependents.put(qName, new HashMap<String, Source>());
}
}
for (Source source : resources.sources().values())
{
if (source.getName() == null)
{
continue;
}
CompilationUnit u = source.getCompilationUnit();
if (u == null)
{
continue;
}
// register QName --> VirtualFile.getName()
for (QName qName : u.topLevelDefinitions)
{
qNames.put(qName, source);
}
}
// setup inheritance-based dependencies...
for (Source source : sources)
{
if (source == null) continue;
CompilationUnit u = source.getCompilationUnit();
if (u == null) continue;
addDependents(source, u.inheritance, dependents);
addDependents(source, u.namespaces, dependents);
addDependents(source, u.types, dependents);
addDependents(source, u.expressions, dependents);
}
Logger logger = ThreadLocalToolkit.getLogger();
// if any of the Source objects in ResourceContainer is bad, obsolete the originating Source.
for (Source source : resources.sources().values())
{
CompilationUnit u = source.getCompilationUnit();
if (source.hasError() ||
(u != null && !u.isDone() && !u.hasTypeInfo) ||
source.isUpdated() ||
(u != null && u.hasAssets() && u.getAssets().isUpdated()))
{
resourceDelegates.add(source.getNameForReporting());
source.removeCompilationUnit();
}
}
reportObsoletedSwcSources(swcContext, l10n, logger);
reportShadowedSwcSources(swcSources, sourceList, sourcePath, resources, l10n, logger, sources);
// identify obsolete CompilationUnit
// - NotFullyCompiled
// - SourceNoLongerExists
// - SourceFileUpdated
// - AssedUpdated
for (Iterator<Source> iterator = sources.iterator(); iterator.hasNext();)
{
Source s = iterator.next();
CompilationUnit u = s.getCompilationUnit();
// Sources for internal classes like Object never reach the done state or have typeInfo.
if (s.hasError() ||
(!s.isInternal() && (u != null && !u.isDone() && !u.hasTypeInfo)) ||
resourceDelegates.contains(s.getName()))
{
affected.put(s.getName(), s);
reasons.put(s.getName(), l10n.getLocalizedTextString(new NotFullyCompiled()));
iterator.remove();
}
else if (!s.exists())
{
updated.put(s.getName(), s);
reasons.put(s.getName(), l10n.getLocalizedTextString(new SourceNoLongerExists()));
if (u != null)
{
for (QName qName : u.topLevelDefinitions)
{
namespaces.add(qName.toString());
deleted.put(qName, s);
}
}
iterator.remove();
}
else if (s.isUpdated())
{
// signature optimization:
// read the old signature from the incremental cache
// generate a new signature from the current source
// compare -- if stable, we don't have to recompile dependencies
boolean signatureIsStable = false;
if ((u != null) &&
(!configuration.getCompilerConfiguration().getDisableIncrementalOptimizations()) &&
// skip MXML sources:
// MXML is too complicated to parse/codegen at this point in
// order to generate and compare a new checksum
(!s.getMimeType().equals(MimeMappings.MXML)))
{
final Long persistedCRC = u.getSignatureChecksum();
if (persistedCRC != null)
{
assert (s.getMimeType().equals(MimeMappings.ABC) ||
s.getMimeType().equals(MimeMappings.AS));
//TODO if we calculate a new checksum that does not match,
// can we store this checksum and not recompute it later?
final Long currentCRC = computeSignatureChecksum(configuration, s);
signatureIsStable = (currentCRC != null) &&
(persistedCRC.compareTo(currentCRC) == 0);
// if (SignatureExtension.debug)
// {
// final String name = u.getSource().getName();
// SignatureExtension.debug("*** FILE UPDATED: Signature "
// + (signatureIsStable ? "IS" : "IS NOT")
// + " stable ***");
// SignatureExtension.debug("PERSISTED CRC32: " + persistedCRC + "\t--> " + name);
// SignatureExtension.debug("CURRENT CRC32: " + currentCRC + "\t--> " + name);
// }
}
}
// if the class signature is stable (it has not changed since the last compile)
// then we can invalidate and recompile the updated unit alone
// otherwise we default to a chain reaction, invalidating _all_ dependent units
if (signatureIsStable)
{
updatedWithStableSignature.put(s.getName(), s);
}
else
{
updated.put(s.getName(), s);
}
reasons.put(s.getName(), l10n.getLocalizedTextString(new SourceFileUpdated()));
iterator.remove();
}
else if (u != null && u.hasAssets() && u.getAssets().isUpdated())
{
updated.put(s.getName(), s);
reasons.put(s.getName(), l10n.getLocalizedTextString(new AssetUpdated()));
iterator.remove();
}
}
// permanently remove the deleted Source objects from SourcePath
//
// Note: this step is currently necessary because the location-updating loop that follows iterates over
// 'sources', which has had deleted entries remove. So here we iterate directly over the deleted
// entries. (Note also that 'reasons' already has an entry for this source.)
//
for (Source source : deleted.values())
{
if (source.isSourcePathOwner())
{
SourcePath sp = (SourcePath) source.getOwner();
sp.removeSource(source);
if (ascContext != null)
{
CompilationUnit u = source.getCompilationUnit();
if (u != null)
{
for (QName defName : u.topLevelDefinitions)
{
ascContext.removeUserDefined(defName.toString());
}
}
}
}
}