Search in sources :

Example 1 with Pie

use of mb.pie.api.Pie in project spoofax by metaborg.

the class GenerateSourcesBuilder method buildStratego.

private void buildStratego(GenerateSourcesBuilder.Input input, Origin sdfOrigin) throws IOException, MetaborgException {
    final File targetMetaborgDir = toFile(paths.targetMetaborgDir());
    final File strFile = input.strFile;
    final Boolean strEnabled = input.strEnabled;
    if (strFile != null && strEnabled) {
        require(strFile, FileExistsStamper.instance);
        if (!strFile.exists()) {
            throw new IOException("Main Stratego file at " + strFile + " does not exist");
        }
        boolean buildStrJavaStrat = input.strJavaStratPackage != null && input.strJavaStratFile != null;
        if (buildStrJavaStrat) {
            require(input.strJavaStratFile, FileExistsStamper.instance);
            if (!input.strJavaStratFile.exists()) {
                throw new IOException("Main Stratego Java strategies file at " + input.strJavaStratFile + " does not exist");
            }
        }
        final Arguments extraArgs = new Arguments();
        extraArgs.addAll(input.strjArgs);
        final File outputFile;
        final File depPath;
        final File outputDir;
        if (input.strFormat == StrategoFormat.ctree) {
            outputFile = FileUtils.getFile(targetMetaborgDir, "stratego.ctree");
            depPath = outputFile;
            outputDir = depPath;
            extraArgs.add("-F");
        } else {
            depPath = toFile(paths.strSrcGenJavaTransDir(input.languageId.id));
            outputDir = toFile(paths.strSrcGenJavaDir());
            outputFile = toFile(paths.strSrcGenJavaTransDir(input.languageId.id).resolveFile("Main.java"));
            extraArgs.add("-la", "java-front");
            if (buildStrJavaStrat) {
                extraArgs.add("-la", input.strJavaStratPackage);
            }
        }
        if (input.strExternalJarFlags != null) {
            extraArgs.addLine(input.strExternalJarFlags);
        }
        final File cacheDir = toFile(paths.strCacheDir());
        if (input.strategoVersion == StrategoVersion.v1) {
            final Strj.Input strjInput = new Strj.Input(context, strFile, outputFile, depPath, input.strJavaPackage, true, true, input.strjIncludeDirs, input.strjIncludeFiles, Lists.newArrayList(), cacheDir, extraArgs, sdfOrigin);
            final Origin strjOrigin = Strj.origin(strjInput);
            requireBuild(strjOrigin);
            return;
        }
        /*
             * Make sure to require all the sdf stuff before running the stratego compiler which will search for the
             * generated stratego files.
             */
        requireBuild(sdfOrigin);
        logger.info("> Compile Stratego code using the incremental compiler");
        final File projectLocation = context.resourceService().localPath(paths.root());
        assert projectLocation != null;
        /*
             * Make sure Pluto also understands which files Pie will require.
             */
        final Set<Path> changedFiles = getChangedFiles(projectLocation);
        final Set<ResourceKey> changedResources = new HashSet<>(changedFiles.size() * 2);
        for (Path changedFile : changedFiles) {
            require(changedFile.toFile(), FileHashStamper.instance);
            changedResources.add(new FSPath(changedFile));
        }
        final ArrayList<IModuleImportService.ModuleIdentifier> linkedLibraries = new ArrayList<>();
        final ArrayList<ResourcePath> strjIncludeDirs = new ArrayList<>();
        for (File strjIncludeDir : input.strjIncludeDirs) {
            FSPath fsPath = new FSPath(strjIncludeDir);
            strjIncludeDirs.add(fsPath);
        }
        final Arguments newArgs = GenerateSourcesBuilder.splitOffLinkedLibrariesIncludeDirs(extraArgs, linkedLibraries, strjIncludeDirs, projectLocation.getPath());
        final String strFileName = strFile.getName();
        final String mainModuleName = strFileName.substring(0, strFileName.length() - ".str2".length());
        final boolean legacyStratego = false;
        final boolean isLibrary = false;
        final ModuleIdentifier mainModuleIdentifier = new ModuleIdentifier(legacyStratego, isLibrary, mainModuleName, new FSPath(strFile));
        final ResourcePath projectPath = new FSPath(projectLocation);
        final String packageName = NameUtil.toJavaId(input.languageId.id) + ".trans";
        final ResourcePath str2libReplicateDir = new FSPath(context.resourceService().localPath(paths.targetClassesDir()));
        final ArrayList<Supplier<Stratego2LibInfo>> str2libraries = new ArrayList<>(input.str2libraries);
        final boolean library = true;
        final boolean autoImportStd = false;
        final CompileInput compileInput = new CompileInput(mainModuleIdentifier, projectPath, new FSPath(outputDir), str2libReplicateDir, packageName, new FSPath(cacheDir), new ArrayList<>(0), strjIncludeDirs, linkedLibraries, newArgs, new ArrayList<>(0), library, autoImportStd, input.strategoShadowJar, input.languageId.id, str2libraries);
        final Task<CompileOutput> compileTask = context.getCompileTask().createTask(compileInput);
        final IPieProvider pieProvider = context.pieProvider();
        final Pie pie = pieProvider.pie();
        synchronized (pie) {
            initCompiler(pieProvider, compileTask, depPath);
            try (final MixedSession session = pie.newSession()) {
                TopDownSession tdSession = session.updateAffectedBy(changedResources);
                session.deleteUnobservedTasks(t -> true, (t, r) -> {
                    if (r != null && Objects.equals(r.getLeafExtension(), "java")) {
                        logger.debug("Deleting garbage from previous build: " + r);
                        return true;
                    }
                    return false;
                });
                final CompileOutput compileOutput = tdSession.getOutput(compileTask);
                if (compileOutput instanceof CompileOutput.Failure) {
                    logger.info("> Incremental compilation of Stratego failed:");
                    final CompileOutput.Failure failure = (CompileOutput.Failure) compileOutput;
                    final ArrayList<String> notes = new ArrayList<>();
                    final ArrayList<String> warnings = new ArrayList<>();
                    final ArrayList<String> errors = new ArrayList<>();
                    for (Message message : failure.messages) {
                        switch(message.severity) {
                            case NOTE:
                                if (message.filename != null && Paths.get(new URI(message.filename)).startsWith(projectLocation.toPath())) {
                                    if (!(message.filename.endsWith(".str") && message instanceof TypeMessage)) {
                                        notes.add(message.toString());
                                    }
                                }
                                break;
                            case WARNING:
                                if (message.filename != null) {
                                    final URI uri = new URI(message.filename);
                                    if (uri.getScheme() != null) {
                                        if (Paths.get(uri).startsWith(projectLocation.toPath())) {
                                            if (!(message.filename.endsWith(".str") && message instanceof TypeMessage)) {
                                                warnings.add(message.toString());
                                            }
                                        }
                                    } else {
                                        logger.error("no uri scheme on filename of message: " + message);
                                    }
                                }
                                break;
                            case ERROR:
                                errors.add(message.toString());
                                break;
                        }
                    }
                    for (String note : notes) {
                        logger.info(note);
                    }
                    for (String warning : warnings) {
                        logger.warn(warning);
                    }
                    for (String error : errors) {
                        logger.error(error);
                    }
                    throw MetaborgException.withoutStackTrace("Incremental Stratego Compilation failed with " + errors.size() + " errors.", null);
                } else {
                    assert compileOutput instanceof CompileOutput.Success;
                    final CompileOutput.Success success = (CompileOutput.Success) compileOutput;
                    for (ResourcePath resultFile : success.resultFiles) {
                        final File file = context.getMbResourceService().toLocalFile(resultFile);
                        provide(file);
                    }
                }
            } catch (ExecException e) {
                throw MetaborgException.withoutStackTrace("Incremental Stratego build failed: " + e.getMessage(), e);
            } catch (InterruptedException e) {
            // Ignore
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        }
    }
}
Also used : Origin(build.pluto.dependency.Origin) TypeMessage(mb.stratego.build.strincr.message.type.TypeMessage) Message(mb.stratego.build.strincr.message.Message) ArrayList(java.util.ArrayList) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) CompileInput(mb.stratego.build.strincr.task.input.CompileInput) SpoofaxInput(org.metaborg.spoofax.meta.core.pluto.SpoofaxInput) ResourcePath(mb.resource.hierarchical.ResourcePath) Supplier(mb.pie.api.Supplier) CompileOutput(mb.stratego.build.strincr.task.output.CompileOutput) ModuleIdentifier(mb.stratego.build.strincr.ModuleIdentifier) CompileInput(mb.stratego.build.strincr.task.input.CompileInput) MixedSession(mb.pie.api.MixedSession) Strj(org.metaborg.spoofax.meta.core.pluto.build.Strj) HashSet(java.util.HashSet) Path(java.nio.file.Path) ResourcePath(mb.resource.hierarchical.ResourcePath) FSPath(mb.resource.fs.FSPath) TopDownSession(mb.pie.api.TopDownSession) TypeMessage(mb.stratego.build.strincr.message.type.TypeMessage) ExecException(mb.pie.api.ExecException) Arguments(org.metaborg.util.cmd.Arguments) IOException(java.io.IOException) Pie(mb.pie.api.Pie) ResourceKey(mb.resource.ResourceKey) FSPath(mb.resource.fs.FSPath) File(java.io.File)

Example 2 with Pie

use of mb.pie.api.Pie 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)2 Path (java.nio.file.Path)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 ExecException (mb.pie.api.ExecException)2 MixedSession (mb.pie.api.MixedSession)2 Pie (mb.pie.api.Pie)2 Supplier (mb.pie.api.Supplier)2 TopDownSession (mb.pie.api.TopDownSession)2 ResourceKey (mb.resource.ResourceKey)2 FSPath (mb.resource.fs.FSPath)2 ResourcePath (mb.resource.hierarchical.ResourcePath)2 ModuleIdentifier (mb.stratego.build.strincr.ModuleIdentifier)2 Message (mb.stratego.build.strincr.message.Message)2 Arguments (org.metaborg.util.cmd.Arguments)2 Origin (build.pluto.dependency.Origin)1 IOException (java.io.IOException)1 URI (java.net.URI)1 URISyntaxException (java.net.URISyntaxException)1 Nullable (javax.annotation.Nullable)1