Search in sources :

Example 6 with DynamicClassLoadingFacet

use of org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet 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

FileObject (org.apache.commons.vfs2.FileObject)6 DynamicClassLoadingFacet (org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet)6 MetaborgException (org.metaborg.core.MetaborgException)4 Nullable (javax.annotation.Nullable)3 ILanguageComponent (org.metaborg.core.language.ILanguageComponent)3 ILanguageImpl (org.metaborg.core.language.ILanguageImpl)3 LanguageIdentifier (org.metaborg.core.language.LanguageIdentifier)3 File (java.io.File)2 ArrayList (java.util.ArrayList)2 Supplier (mb.pie.api.Supplier)2 ValueSupplier (mb.pie.api.ValueSupplier)2 FSPath (mb.resource.fs.FSPath)2 ResourcePath (mb.resource.hierarchical.ResourcePath)2 Stratego2LibInfo (mb.stratego.build.strincr.Stratego2LibInfo)2 IExportConfig (org.metaborg.core.config.IExportConfig)2 IExportVisitor (org.metaborg.core.config.IExportVisitor)2 ILanguageComponentConfig (org.metaborg.core.config.ILanguageComponentConfig)2 LangDirExport (org.metaborg.core.config.LangDirExport)2 LangFileExport (org.metaborg.core.config.LangFileExport)2 ResourceExport (org.metaborg.core.config.ResourceExport)2