use of org.metaborg.core.context.IContext in project spoofax by metaborg.
the class Builder method transform.
private Collection<T> transform(BuildInput input, ILanguageImpl langImpl, FileObject location, Multimap<IContext, A> allAnalysisUnits, Set<FileName> includeFiles, boolean pardoned, Set<FileName> removedResources, Collection<IMessage> extraMessages, RefBool success, IProgress progress, ICancel cancel) throws InterruptedException {
final int size = allAnalysisUnits.size();
progress.setWorkRemaining(size);
final Collection<T> allTransformUnits = Lists.newArrayListWithCapacity(size);
if (size == 0) {
return allTransformUnits;
}
progress.setDescription("Compiling " + size + " file(s) of " + langImpl.belongsTo().name());
logger.debug("Compiling {} analysis results", size);
for (Entry<IContext, Collection<A>> entry : allAnalysisUnits.asMap().entrySet()) {
cancel.throwIfCancelled();
final IContext context = entry.getKey();
final Iterable<A> analysisResults = entry.getValue();
try (IClosableLock lock = context.read()) {
for (A analysisResult : analysisResults) {
cancel.throwIfCancelled();
final FileObject source = analysisResult.source();
final FileName name = source.getName();
if (removedResources.contains(name) || includeFiles.contains(name)) {
// Don't compile removed resources, which the analysis results contain for legacy reasons.
// Don't transform included resources, they should just be parsed and analyzed.
progress.work(1);
continue;
}
if (!analysisResult.valid()) {
logger.warn("Input result for {} is invalid, cannot transform it", source != null ? source.getName().getPath() : "detached source");
progress.work(1);
continue;
}
for (ITransformGoal goal : input.transformGoals) {
cancel.throwIfCancelled();
if (!transformService.available(context, goal)) {
logger.trace("No {} transformation required for {}", goal, context.language());
progress.work(1);
continue;
}
try {
final Collection<TA> results = transformService.transform(analysisResult, context, goal);
for (TA result : results) {
final boolean noErrors = printMessages(result.messages(), goal + " transformation", input, pardoned);
success.and(noErrors);
@SuppressWarnings("unchecked") final T genericResult = (T) result;
allTransformUnits.add(genericResult);
}
progress.work(1);
} catch (TransformException e) {
final String message = String.format("Transformation failed unexpectedly for %s", name);
logger.error(message, e);
final boolean noErrors = printMessage(source, message, e, input, pardoned);
success.and(noErrors);
extraMessages.add(MessageFactory.newBuilderErrorAtTop(location, "Transformation failed unexpectedly", e));
}
}
}
// GTODO: also compile any affected sources
}
}
return allTransformUnits;
}
use of org.metaborg.core.context.IContext 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.context.IContext in project spoofax by metaborg.
the class OutlineService method outline.
@Override
public IOutline outline(ISpoofaxAnalyzeUnit result) throws MetaborgException {
if (!result.valid() || !result.hasAst()) {
return null;
}
final FileObject source = result.source();
final IContext context = result.context();
final ILanguageImpl language = context.language();
final FacetContribution<OutlineFacet> facetContrib = facet(language);
final OutlineFacet facet = facetContrib.facet;
final ILanguageComponent contributor = facetContrib.contributor;
final String strategy = facet.strategyName;
try {
final HybridInterpreter interpreter = strategoRuntimeService.runtime(contributor, context, true);
final IStrategoTerm input = common.builderInputTerm(result.ast(), source, context.location());
final IStrategoTerm outlineTerm = common.invoke(interpreter, input, strategy);
if (outlineTerm == null) {
return null;
}
final IOutline outline = toOutline(outlineTerm, facet.expandTo, contributor.location());
return outline;
} catch (MetaborgException e) {
throw new MetaborgException("Creating outline failed", e);
}
}
use of org.metaborg.core.context.IContext in project spoofax by metaborg.
the class OutlineService method outline.
@Override
public IOutline outline(ISpoofaxParseUnit result) throws MetaborgException {
if (!result.valid()) {
return null;
}
final FileObject source = result.source();
final IProject project = projectService.get(source);
final ILanguageImpl langImpl = result.input().langImpl();
@Nullable IContext context;
if (project == null) {
context = null;
} else {
try {
context = contextService.get(source, project, langImpl);
} catch (ContextException | MetaborgRuntimeException e) {
// Failed to get a context, ignore and use the source file to get a stratego runtime later.
context = null;
}
}
final FacetContribution<OutlineFacet> facetContrib = facet(langImpl);
final OutlineFacet facet = facetContrib.facet;
final ILanguageComponent contributor = facetContrib.contributor;
final String strategy = facet.strategyName;
try {
final HybridInterpreter interpreter;
if (context == null) {
interpreter = strategoRuntimeService.runtime(contributor, source, true);
} else {
interpreter = strategoRuntimeService.runtime(contributor, context, true);
}
final IStrategoTerm input = common.builderInputTerm(result.ast(), source, source);
final IStrategoTerm outlineTerm = common.invoke(interpreter, input, strategy);
if (outlineTerm == null) {
return null;
}
final IOutline outline = toOutline(outlineTerm, facet.expandTo, contributor.location());
return outline;
} catch (MetaborgException e) {
throw new MetaborgException("Creating outline failed", e);
}
}
use of org.metaborg.core.context.IContext in project spoofax by metaborg.
the class Builder method analyze.
private Multimap<IContext, A> analyze(BuildInput input, ILanguageImpl langImpl, FileObject location, Multimap<IContext, P> sourceParseUnits, Iterable<P> includeParseUnits, boolean pardoned, Collection<AU> analyzeUpdates, Set<FileName> removedResources, Collection<IMessage> extraMessages, RefBool success, IProgress progress, ICancel cancel) throws InterruptedException {
final int size = sourceParseUnits.size() + Iterables.size(includeParseUnits);
final Multimap<IContext, A> allAnalyzeUnits = ArrayListMultimap.create();
if (size == 0) {
return allAnalyzeUnits;
}
final Set<Entry<IContext, Collection<P>>> toAnalyze = sourceParseUnits.asMap().entrySet();
final int toAnalyzeSize = toAnalyze.size();
progress.setWorkRemaining(toAnalyzeSize);
progress.setDescription("Analyzing " + size + " file(s) of " + langImpl.belongsTo().name());
logger.debug("Analyzing {} parse results in {} context(s)", size, toAnalyzeSize);
for (Entry<IContext, Collection<P>> entry : toAnalyze) {
cancel.throwIfCancelled();
final IContext context = entry.getKey();
final Iterable<P> parseResults = Iterables.concat(entry.getValue(), includeParseUnits);
try {
try (IClosableLock lock = context.write()) {
analysisResultUpdater.invalidate(parseResults);
final IAnalyzeResults<A, AU> results = analysisService.analyzeAll(parseResults, context, progress.subProgress(1), cancel);
for (A result : results.results()) {
cancel.throwIfCancelled();
final boolean noErrors = printMessages(result.messages(), "Analysis", input, pardoned);
success.and(noErrors);
analysisResultUpdater.update(result, removedResources);
allAnalyzeUnits.put(context, result);
}
analyzeUpdates.addAll(results.updates());
} finally {
context.persist();
}
} catch (AnalysisException e) {
final String message = "Analysis failed unexpectedly";
final boolean noErrors = printMessage(message, e, input, pardoned);
success.and(noErrors);
analysisResultUpdater.error(parseResults, e);
extraMessages.add(MessageFactory.newAnalysisErrorAtTop(location, message, e));
} catch (IOException e) {
final String message = "Persisting analysis data failed unexpectedly";
final boolean noErrors = printMessage(message, e, input, pardoned);
success.and(noErrors);
extraMessages.add(MessageFactory.newAnalysisErrorAtTop(location, message, e));
}
}
return allAnalyzeUnits;
}
Aggregations