use of org.metaborg.core.resource.IdentifiedResourceChange in project spoofax by metaborg.
the class Builder method identifyResources.
private void identifyResources(Iterable<ResourceChange> changes, BuildInput input, Multimap<ILanguageImpl, IdentifiedResourceChange> identifiedChanges, ICancel cancel) throws InterruptedException {
final Iterable<ILanguageImpl> languages = input.buildOrder.languages();
final FileSelector selector = input.selector;
final FileObject location = input.project.location();
for (ResourceChange change : changes) {
cancel.throwIfCancelled();
final FileObject resource = change.resource;
if (selector != null) {
try {
if (!FileSelectorUtils.include(selector, resource, location)) {
continue;
}
} catch (FileSystemException e) {
logger.error("Error determining if {} should be ignored from the build, including it", e, resource);
}
}
final IdentifiedResource identifiedResource = languageIdentifier.identifyToResource(resource, languages);
if (identifiedResource != null) {
final IdentifiedResourceChange identifiedChange = new IdentifiedResourceChange(change, identifiedResource);
identifiedChanges.put(identifiedChange.language, identifiedChange);
}
}
}
use of org.metaborg.core.resource.IdentifiedResourceChange in project spoofax by metaborg.
the class Builder method updateLanguageResources.
private Collection<FileObject> updateLanguageResources(BuildInput input, ILanguageImpl language, LanguageBuildDiff diff, IBuildOutputInternal<P, A, AU, T> output, boolean pardoned, IProgress progress, ICancel cancel) throws InterruptedException {
cancel.throwIfCancelled();
final boolean analyze = input.analyze && analysisService.available(language);
final boolean transform = input.transform;
progress.setWorkRemaining(10 + (analyze ? 45 : 0) + (transform ? 45 : 0));
final Iterable<IdentifiedResourceChange> sourceChanges = diff.sourceChanges;
final Iterable<IdentifiedResourceChange> includeChanges = diff.includeChanges;
final Set<FileName> includes = Sets.newHashSet();
for (IdentifiedResourceChange includeChange : includeChanges) {
includes.add(includeChange.change.resource.getName());
}
final FileObject location = input.project.location();
final Collection<FileObject> changedSources = Sets.newHashSet();
final Set<FileName> removedResources = Sets.newHashSet();
final Collection<IMessage> extraMessages = Lists.newLinkedList();
final RefBool success = new RefBool(true);
logger.info("Building {} sources, {} includes of {}", Iterables.size(sourceChanges), Iterables.size(includeChanges), language);
// Parse
cancel.throwIfCancelled();
final Collection<P> sourceParseUnits = parse(input, language, sourceChanges, pardoned, changedSources, removedResources, extraMessages, success, progress.subProgress(5), cancel);
// GTODO: when a new context is created, all include files need to be parsed and analyzed in that context, this
// approach does not do that!
final Collection<P> includeParseUnits = parse(input, language, includeChanges, pardoned, changedSources, removedResources, extraMessages, success, progress.subProgress(5), cancel);
final Iterable<P> allParseResults = Iterables.concat(sourceParseUnits, includeParseUnits);
// Analyze
cancel.throwIfCancelled();
final Multimap<IContext, A> allAnalyzeUnits;
final Collection<AU> allAnalyzeUpdates = Lists.newArrayList();
if (analyze) {
// Segregate by context
final Multimap<IContext, P> parseUnitsPerContext = ArrayListMultimap.create();
for (P parseResult : sourceParseUnits) {
cancel.throwIfCancelled();
final FileObject resource = parseResult.source();
final ILanguageImpl langImpl = parseResult.input().langImpl();
try {
if (contextService.available(langImpl)) {
final IContext context = contextService.get(resource, input.project, langImpl);
parseUnitsPerContext.put(context, parseResult);
}
} catch (ContextException e) {
final String message = String.format("Failed to retrieve context for parse result of %s", resource);
printMessage(resource, message, e, input, pardoned);
extraMessages.add(MessageFactory.newAnalysisErrorAtTop(resource, "Failed to retrieve context", e));
}
}
// Run analysis
cancel.throwIfCancelled();
allAnalyzeUnits = analyze(input, language, location, parseUnitsPerContext, includeParseUnits, pardoned, allAnalyzeUpdates, removedResources, extraMessages, success, progress.subProgress(45), cancel);
} else {
allAnalyzeUnits = ArrayListMultimap.create();
}
// Transform
cancel.throwIfCancelled();
final Collection<T> allTransformUnits;
if (transform) {
allTransformUnits = transform(input, language, location, allAnalyzeUnits, includes, pardoned, removedResources, extraMessages, success, progress.subProgress(45), cancel);
} else {
allTransformUnits = Lists.newLinkedList();
}
printMessages(extraMessages, "Something", input, pardoned);
output.add(success.get(), removedResources, includes, changedSources, allParseResults, allAnalyzeUnits.values(), allAnalyzeUpdates, allTransformUnits, extraMessages);
final Collection<FileObject> newResources = Lists.newArrayList();
for (T transformUnit : allTransformUnits) {
for (ITransformOutput transformOutput : transformUnit.outputs()) {
final FileObject outputFile = transformOutput.output();
if (outputFile != null) {
newResources.add(outputFile);
}
}
}
return newResources;
}
use of org.metaborg.core.resource.IdentifiedResourceChange in project spoofax by metaborg.
the class FilesBuildState method includeDiff.
private Iterable<IdentifiedResourceChange> includeDiff(LanguageBuildState newState, Iterable<IdentifiedResource> newFiles) {
final Collection<IdentifiedResourceChange> changes = Lists.newLinkedList();
final Set<FileName> existingFiles = Sets.newHashSet(include.files);
for (IdentifiedResource identifiedResource : newFiles) {
final FileObject resource = identifiedResource.resource;
final FileName name = resource.getName();
final long newModification = newState.include.add(resource);
existingFiles.remove(name);
if (include.files.contains(name)) {
final long existingModification = include.modification.get(name);
if (existingModification != newModification) {
changes.add(new IdentifiedResourceChange(new ResourceChange(resource, ResourceChangeKind.Modify), identifiedResource));
}
} else {
changes.add(new IdentifiedResourceChange(new ResourceChange(resource, ResourceChangeKind.Create), identifiedResource));
}
}
for (FileName name : existingFiles) {
newState.include.remove(name);
final FileObject resource = resourceService.resolve(name.getURI());
final IdentifiedResource identifiedResource = languageIdentifierService.identifyToResource(resource, Iterables2.singleton(language));
if (identifiedResource != null) {
changes.add(new IdentifiedResourceChange(new ResourceChange(resource, ResourceChangeKind.Delete), identifiedResource));
}
}
return changes;
}
use of org.metaborg.core.resource.IdentifiedResourceChange in project spoofax by metaborg.
the class Builder method build.
@Override
public IBuildOutput<P, A, AU, T> build(BuildInput input, IProgress progress, ICancel cancel) throws InterruptedException {
cancel.throwIfCancelled();
final Multimap<ILanguageImpl, IdentifiedResourceChange> changes = ArrayListMultimap.create();
identifyResources(input.sourceChanges, input, changes, cancel);
if (changes.size() == 0) {
// When there are no source changes, keep the old state and skip building.
final IBuildOutputInternal<P, A, AU, T> buildOutput = buildOutputProvider.get();
buildOutput.setState(input.state);
return buildOutput;
}
cancel.throwIfCancelled();
logger.info("Building " + input.project.location());
final BuildState newState = new BuildState();
final IBuildOutputInternal<P, A, AU, T> buildOutput = buildOutputProvider.get();
buildOutput.setState(newState);
final Iterable<ILanguageImpl> buildOrder = input.buildOrder.buildOrder();
progress.setWorkRemaining(Iterables.size(buildOrder));
for (ILanguageImpl language : buildOrder) {
cancel.throwIfCancelled();
final LanguageBuildState languageState = input.state.get(resourceService, languageIdentifier, language);
final Collection<IdentifiedResourceChange> sourceChanges = changes.get(language);
if (sourceChanges.size() == 0) {
// When there are no source changes for this language, keep the old state and don't build.
newState.add(language, languageState);
continue;
}
final Iterable<FileObject> includePaths = input.includePaths.get(language);
final Iterable<IdentifiedResource> includeFiles = languagePathService.toFiles(includePaths, language);
final LanguageBuildDiff diff = languageState.diff(changes.get(language), includeFiles);
final boolean pardoned = input.pardonedLanguages.contains(language);
final Collection<FileObject> newResources = updateLanguageResources(input, language, diff, buildOutput, pardoned, progress.subProgress(1), cancel);
final Iterable<ResourceChange> newResourceChanges = ResourceUtils.toChanges(newResources, ResourceChangeKind.Create);
identifyResources(newResourceChanges, input, changes, cancel);
newState.add(language, diff.newState);
}
final IMessagePrinter printer = input.messagePrinter;
if (printer != null) {
printer.printSummary();
}
return buildOutput;
}
use of org.metaborg.core.resource.IdentifiedResourceChange in project spoofax by metaborg.
the class Builder method parse.
private Collection<P> parse(BuildInput input, ILanguageImpl langImpl, Iterable<IdentifiedResourceChange> changes, boolean pardoned, Collection<FileObject> changedResources, Set<FileName> removedResources, Collection<IMessage> extraMessages, RefBool success, IProgress progress, ICancel cancel) throws InterruptedException {
final int size = Iterables.size(changes);
progress.setWorkRemaining(size);
final Collection<P> allParseUnits = Lists.newArrayListWithCapacity(size);
if (size == 0) {
return allParseUnits;
}
progress.setDescription("Parsing " + size + " file(s) of " + langImpl.belongsTo().name());
logger.debug("Parsing {} resources", size);
for (IdentifiedResourceChange identifiedChange : changes) {
cancel.throwIfCancelled();
final ResourceChange change = identifiedChange.change;
final FileObject resource = change.resource;
final ILanguageImpl dialect = identifiedChange.dialect;
final ResourceChangeKind changeKind = change.kind;
try {
if (changeKind == ResourceChangeKind.Delete) {
parseResultUpdater.remove(resource);
removedResources.add(resource.getName());
// LEGACY: add empty parse result, to indicate to analysis that this resource was
// removed. There is special handling in updating the analysis result processor, the marker
// updater, and the compiler, to exclude removed resources.
final I inputUnit = unitService.emptyInputUnit(resource, langImpl, dialect);
final P emptyParseResult = unitService.emptyParseUnit(inputUnit);
allParseUnits.add(emptyParseResult);
// Don't add resource as changed when it has been deleted, because it does not exist any more.
progress.work(1);
} else {
final String sourceText = sourceTextService.text(resource);
parseResultUpdater.invalidate(resource);
final I inputUnit = unitService.inputUnit(resource, sourceText, langImpl, dialect);
final P parseResult = syntaxService.parse(inputUnit, progress.subProgress(1), cancel);
final boolean noErrors = printMessages(parseResult.messages(), "Parsing", input, pardoned);
success.and(noErrors);
allParseUnits.add(parseResult);
parseResultUpdater.update(resource, parseResult);
changedResources.add(resource);
}
} catch (ParseException e) {
final String message = logger.format("Parsing {} failed unexpectedly", resource);
final boolean noErrors = printMessage(resource, message, e, input, pardoned);
success.and(noErrors);
parseResultUpdater.error(resource, e);
extraMessages.add(MessageFactory.newParseErrorAtTop(resource, "Parsing failed unexpectedly", e));
changedResources.add(resource);
} catch (IOException e) {
final String message = logger.format("Getting source text for {} failed unexpectedly", resource);
final boolean noErrors = printMessage(resource, message, e, input, pardoned);
success.and(noErrors);
final I inputUnit = unitService.emptyInputUnit(resource, langImpl, dialect);
parseResultUpdater.error(resource, new ParseException(inputUnit, e));
extraMessages.add(MessageFactory.newParseErrorAtTop(resource, "Getting source text failed unexpectedly", e));
changedResources.add(resource);
}
}
return allParseUnits;
}
Aggregations