Search in sources :

Example 1 with CheckOpenModuleOutput

use of mb.stratego.build.strincr.task.output.CheckOpenModuleOutput in project spoofax by metaborg.

the class StrategoPieAnalyzePrimitive method call.

@Override
@Nullable
protected IStrategoTerm call(IStrategoTerm current, Strategy[] svars, IStrategoTerm[] tvars, ITermFactory factory, IContext context) throws MetaborgException, IOException {
    final IStrategoAppl ast = TermUtils.toApplAt(current, 0);
    final String path = TermUtils.toJavaStringAt(current, 1);
    // final String projectPath = TermUtils.toJavaStringAt(current, 2);
    final String moduleName;
    if (!(ast.getName().equals("Module") && ast.getSubtermCount() == 2)) {
        moduleName = path;
    } else {
        moduleName = TermUtils.toJavaStringAt(ast, 0);
    }
    final IProject project = context.project();
    if (project == null) {
        logger.warn("Cannot find project for opened file, cancelling analysis. ");
        return null;
    }
    if (languageSpecServiceProvider == null || languageServiceProvider == null || pieProviderProvider == null) {
        // Indicates that meta-Spoofax is not available (ISpoofaxLanguageSpecService cannot be injected), but this
        // should never happen because this primitive is inside meta-Spoofax. Check for null just in case.
        logger.error("Spoofax meta services is not available; static injection failed");
        return null;
    }
    @Nullable final ISpoofaxLanguageSpec languageSpec = getLanguageSpecification(project);
    if (languageSpec == null) {
        logger.warn("Cannot find language specification for project of opened file, cancelling analysis. ");
        return null;
    }
    final ISpoofaxLanguageSpecConfig config = languageSpec.config();
    final FileObject baseLoc = languageSpec.location();
    final SpoofaxLangSpecCommonPaths paths = new SpoofaxLangSpecCommonPaths(baseLoc);
    String strMainModule = NameUtil.toJavaId(config.strategoName().toLowerCase());
    final Iterable<FileObject> strRoots = languagePathService.sourcePaths(project, SpoofaxConstants.LANG_STRATEGO_NAME);
    @Nullable File strMainFile;
    final FileObject strMainFileCandidate = config.strVersion().findStrMainFile(paths, strRoots, config.strategoName());
    if (strMainFileCandidate != null && strMainFileCandidate.exists()) {
        strMainFile = resourceService.localPath(strMainFileCandidate);
        if (strMainFile == null || !strMainFile.exists()) {
            logger.info("Main Stratego2 file at " + strMainFile + " does not exist");
            strMainFile = resourceService.localFile(resourceService.resolve(baseLoc, path));
            strMainModule = moduleName;
        }
    } else {
        logger.info("Main Stratego2 file with name " + strMainModule + ".str2 does not exist");
        strMainFile = resourceService.localFile(resourceService.resolve(baseLoc, path));
        strMainModule = moduleName;
    }
    final File strFile = resourceService.localFile(resourceService.resolve(baseLoc, path));
    @Nullable final String strExternalJarFlags = config.strExternalJarFlags();
    final Iterable<FileObject> strIncludePaths = Iterables.concat(languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_STRATEGO_NAME), languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_STRATEGO2_NAME));
    final FileObject strjIncludesReplicateDir = paths.replicateDir().resolveFile("strj-includes");
    final ArrayList<ResourcePath> strjIncludeDirs = new ArrayList<>();
    for (FileObject strIncludePath : strIncludePaths) {
        if (!strIncludePath.exists()) {
            continue;
        }
        if (strIncludePath.isFolder()) {
            strjIncludeDirs.add(new FSPath(resourceService.localFileUpdate(strIncludePath, strjIncludesReplicateDir)));
        }
    }
    final Arguments extraArgs = new Arguments();
    extraArgs.addAll(config.strArgs());
    extraArgs.add("-la", "java-front");
    if (strExternalJarFlags != null) {
        extraArgs.addLine(strExternalJarFlags);
    }
    final File projectLocation = resourceService.localPath(paths.root());
    assert projectLocation != null;
    final ResourcePath projectPath = new FSPath(projectLocation);
    final ArrayList<Supplier<Stratego2LibInfo>> str2libraries = new ArrayList<>();
    for (LanguageIdentifier sourceDep : config.sourceDeps()) {
        @Nullable final ILanguageImpl sourceDepImpl = languageServiceProvider.get().getImpl(sourceDep);
        if (sourceDepImpl == null) {
            continue;
        }
        for (ILanguageComponent sourceDepImplComp : sourceDepImpl.components()) {
            final String[] str2libProject = { null };
            for (IExportConfig export : sourceDepImplComp.config().exports()) {
                if (str2libProject[0] != null) {
                    break;
                }
                export.accept(new IExportVisitor() {

                    @Override
                    public void visit(LangDirExport resource) {
                    }

                    @Override
                    public void visit(LangFileExport resource) {
                        if (resource.language.equals("StrategoLang") && resource.file.endsWith("str2lib")) {
                            str2libProject[0] = resource.file;
                        }
                    }

                    @Override
                    public void visit(ResourceExport resource) {
                    }
                });
            }
            if (str2libProject[0] != null) {
                final String str2IncludeDir = "str2-includes/" + sourceDepImplComp.id().toFullFileString() + "-" + sourceDepImplComp.sequenceId();
                final ResourcePath str2LibFile = new FSPath(resourceService.localFileUpdate(sourceDepImplComp.location().resolveFile(str2libProject[0]), paths.replicateDir().resolveFile(str2IncludeDir)));
                @Nullable final DynamicClassLoadingFacet facet = sourceDepImplComp.facet(DynamicClassLoadingFacet.class);
                if (facet == null) {
                    continue;
                }
                final ArrayList<ResourcePath> jarFiles = new ArrayList<>(facet.jarFiles.size());
                for (FileObject file : facet.jarFiles) {
                    jarFiles.add(new FSPath(resourceService.localFileUpdate(file, paths.replicateDir().resolveFile(str2IncludeDir))));
                }
                str2libraries.add(new ValueSupplier<>(new Stratego2LibInfo(str2LibFile, jarFiles)));
            }
        }
    }
    final ArrayList<STask<?>> sdfTasks = new ArrayList<>(0);
    // Gather all Stratego files to be checked for changes
    final Set<Path> changedFiles = GenerateSourcesBuilder.getChangedFiles(projectLocation);
    final Set<ResourceKey> changedResources = new HashSet<>(changedFiles.size() * 2);
    for (Path changedFile : changedFiles) {
        changedResources.add(new FSPath(changedFile));
    }
    final ArrayList<IModuleImportService.ModuleIdentifier> linkedLibraries = new ArrayList<>();
    GenerateSourcesBuilder.splitOffLinkedLibrariesIncludeDirs(extraArgs, linkedLibraries, strjIncludeDirs, projectLocation.getPath());
    final LastModified<IStrategoTerm> astWLM = new LastModified<>(ast, Instant.now().getEpochSecond());
    final boolean isLibrary = false;
    final ModuleIdentifier moduleIdentifier = new ModuleIdentifier(strFile.getName().endsWith(".str"), isLibrary, moduleName, new FSPath(strFile));
    final ModuleIdentifier mainModuleIdentifier = new ModuleIdentifier(strMainFile.getName().endsWith(".str"), isLibrary, strMainModule, new FSPath(strMainFile));
    final boolean autoImportStd = false;
    final IModuleImportService.ImportResolutionInfo importResolutionInfo = new IModuleImportService.ImportResolutionInfo(sdfTasks, strjIncludeDirs, linkedLibraries, str2libraries);
    final CheckModuleInput checkModuleInput = new CheckModuleInput(new FrontInput.FileOpenInEditor(moduleIdentifier, importResolutionInfo, astWLM, autoImportStd), mainModuleIdentifier, projectPath);
    final Task<CheckOpenModuleOutput> checkModuleTask = checkModuleProvider.get().createTask(checkModuleInput);
    final IPieProvider pieProvider = pieProviderProvider.get();
    final Pie pie = pieProvider.pie();
    final IStrategoList.Builder errors = B.listBuilder();
    final IStrategoList.Builder warnings = B.listBuilder();
    final IStrategoList.Builder notes = B.listBuilder();
    final CheckOpenModuleOutput analysisInformation;
    // noinspection SynchronizationOnLocalVariableOrMethodParameter
    synchronized (pie) {
        GenerateSourcesBuilder.initCompiler(pieProvider, checkModuleTask);
        try (final MixedSession session = pie.newSession()) {
            TopDownSession tdSession = session.updateAffectedBy(changedResources);
            session.deleteUnobservedTasks(t -> true, (t, r) -> {
                if (Objects.equals(r.getLeafExtension(), "java")) {
                    logger.debug("Deleting garbage from previous build: " + r);
                    return true;
                }
                return false;
            });
            analysisInformation = tdSession.getOutput(checkModuleTask);
        } catch (ExecException e) {
            logger.warn("Incremental Stratego build failed", e);
            return null;
        } catch (InterruptedException e) {
            // Ignore
            return null;
        }
    }
    for (Message message : analysisInformation.messages) {
        final IStrategoString term = factory.makeString(message.locationTermString);
        if (message.filename == null) {
            logger.debug("No origins for message: " + message);
        } else {
            // otherwise filename would have also been null
            assert message.sourceRegion != null;
            if (!resourceService.resolve(message.filename).equals(resourceService.resolve(baseLoc, path))) {
                continue;
            }
            final ImploderAttachment imploderAttachment = ImploderAttachment.createCompactPositionAttachment(message.filename, message.sourceRegion.startRow, message.sourceRegion.startColumn, message.sourceRegion.startOffset, message.sourceRegion.endOffset);
            term.putAttachment(imploderAttachment);
        }
        final IStrategoTuple messageTuple = B.tuple(term, B.string(message.getMessage()));
        switch(message.severity) {
            case ERROR:
                errors.add(messageTuple);
                break;
            case NOTE:
                notes.add(messageTuple);
                break;
            case WARNING:
                warnings.add(messageTuple);
                break;
        }
    }
    return B.tuple(analysisInformation.astWithCasts, B.list(errors), B.list(warnings), B.list(notes));
}
Also used : IExportConfig(org.metaborg.core.config.IExportConfig) CheckModuleInput(mb.stratego.build.strincr.task.input.CheckModuleInput) ArrayList(java.util.ArrayList) FrontInput(mb.stratego.build.strincr.task.input.FrontInput) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) IStrategoTuple(org.spoofax.interpreter.terms.IStrategoTuple) IStrategoList(org.spoofax.interpreter.terms.IStrategoList) IStrategoString(org.spoofax.interpreter.terms.IStrategoString) LastModified(mb.stratego.build.util.LastModified) ResourcePath(mb.resource.hierarchical.ResourcePath) IExportVisitor(org.metaborg.core.config.IExportVisitor) LangDirExport(org.metaborg.core.config.LangDirExport) IModuleImportService(mb.stratego.build.strincr.IModuleImportService) FileObject(org.apache.commons.vfs2.FileObject) ImploderAttachment(org.spoofax.jsglr.client.imploder.ImploderAttachment) MixedSession(mb.pie.api.MixedSession) HashSet(java.util.HashSet) LangFileExport(org.metaborg.core.config.LangFileExport) ISpoofaxLanguageSpecConfig(org.metaborg.spoofax.meta.core.config.ISpoofaxLanguageSpecConfig) Arguments(org.metaborg.util.cmd.Arguments) IPieProvider(org.metaborg.spoofax.meta.core.pluto.build.main.IPieProvider) ResourceKey(mb.resource.ResourceKey) DynamicClassLoadingFacet(org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet) ResourceExport(org.metaborg.core.config.ResourceExport) FSPath(mb.resource.fs.FSPath) ILanguageComponent(org.metaborg.core.language.ILanguageComponent) File(java.io.File) Nullable(javax.annotation.Nullable) STask(mb.pie.api.STask) IStrategoTerm(org.spoofax.interpreter.terms.IStrategoTerm) Message(mb.stratego.build.strincr.message.Message) IStrategoAppl(org.spoofax.interpreter.terms.IStrategoAppl) Stratego2LibInfo(mb.stratego.build.strincr.Stratego2LibInfo) ISpoofaxLanguageSpec(org.metaborg.spoofax.meta.core.project.ISpoofaxLanguageSpec) Supplier(mb.pie.api.Supplier) ValueSupplier(mb.pie.api.ValueSupplier) ModuleIdentifier(mb.stratego.build.strincr.ModuleIdentifier) Path(java.nio.file.Path) ResourcePath(mb.resource.hierarchical.ResourcePath) FSPath(mb.resource.fs.FSPath) TopDownSession(mb.pie.api.TopDownSession) ExecException(mb.pie.api.ExecException) CheckOpenModuleOutput(mb.stratego.build.strincr.task.output.CheckOpenModuleOutput) Pie(mb.pie.api.Pie) IProject(org.metaborg.core.project.IProject) LanguageIdentifier(org.metaborg.core.language.LanguageIdentifier) ILanguageImpl(org.metaborg.core.language.ILanguageImpl) SpoofaxLangSpecCommonPaths(org.metaborg.spoofax.meta.core.build.SpoofaxLangSpecCommonPaths) Nullable(javax.annotation.Nullable)

Aggregations

File (java.io.File)1 Path (java.nio.file.Path)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Nullable (javax.annotation.Nullable)1 ExecException (mb.pie.api.ExecException)1 MixedSession (mb.pie.api.MixedSession)1 Pie (mb.pie.api.Pie)1 STask (mb.pie.api.STask)1 Supplier (mb.pie.api.Supplier)1 TopDownSession (mb.pie.api.TopDownSession)1 ValueSupplier (mb.pie.api.ValueSupplier)1 ResourceKey (mb.resource.ResourceKey)1 FSPath (mb.resource.fs.FSPath)1 ResourcePath (mb.resource.hierarchical.ResourcePath)1 IModuleImportService (mb.stratego.build.strincr.IModuleImportService)1 ModuleIdentifier (mb.stratego.build.strincr.ModuleIdentifier)1 Stratego2LibInfo (mb.stratego.build.strincr.Stratego2LibInfo)1 Message (mb.stratego.build.strincr.message.Message)1 CheckModuleInput (mb.stratego.build.strincr.task.input.CheckModuleInput)1