Search in sources :

Example 1 with ResourcePath

use of mb.resource.hierarchical.ResourcePath in project spoofax by metaborg.

the class LanguageSpecBuilder method generateSourcesBuilderInput.

private GenerateSourcesBuilder.Input generateSourcesBuilderInput(LanguageSpecBuildInput input) throws FileSystemException, MetaborgException {
    final ISpoofaxLanguageSpec languageSpec = input.languageSpec();
    final ISpoofaxLanguageSpecConfig config = languageSpec.config();
    final FileObject baseLoc = input.languageSpec().location();
    final SpoofaxLangSpecCommonPaths paths = new SpoofaxLangSpecCommonPaths(baseLoc);
    final FileObject buildInfoLoc = paths.plutoBuildInfoDir();
    final SpoofaxContext context = new SpoofaxContext(baseLoc, buildInfoLoc);
    // Sort source dependencies to ensure deterministic input.
    final ArrayList<LanguageIdentifier> sourceDeps = new ArrayList<>(config.sourceDeps());
    Collections.sort(sourceDeps);
    // SDF
    final Boolean sdfEnabled = config.sdfEnabled();
    final String sdfModule = config.sdfName();
    final JSGLRVersion jsglrVersion = config.jsglrVersion();
    final Boolean checkOverlap = config.checkOverlap();
    final Boolean checkPriorities = config.checkPriorities();
    final FileObject sdfFileCandidate;
    final SdfVersion sdfVersion = config.sdfVersion();
    final Sdf2tableVersion sdf2tableVersion = config.sdf2tableVersion();
    switch(sdfVersion) {
        case sdf2:
            final Iterable<FileObject> sdfRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_SDF_NAME);
            sdfFileCandidate = paths.findSyntaxMainFile(sdfRoots, sdfModule);
            break;
        case sdf3:
            sdfFileCandidate = paths.syntaxSrcGenMainFile(sdfModule);
            break;
        default:
            throw new MetaborgException("Unknown SDF version: " + sdfVersion);
    }
    @Nullable final File sdfFile;
    if (sdfFileCandidate != null && sdfFileCandidate.exists()) {
        sdfFile = resourceService.localPath(sdfFileCandidate);
    } else {
        sdfFile = null;
    }
    @Nullable final File sdfExternalDef;
    final String sdfExternalDefStr = config.sdfExternalDef();
    if (sdfExternalDefStr != null) {
        final FileObject sdfExternalDefLoc = resourceService.resolve(sdfExternalDefStr);
        if (!sdfExternalDefLoc.exists()) {
            throw new MetaborgException("External SDF definition at " + sdfExternalDefLoc + " does not exist");
        }
        sdfExternalDef = resourceService.localFile(sdfExternalDefLoc);
    } else {
        sdfExternalDef = null;
    }
    final Iterable<FileObject> sdfIncludePaths = languagePathService.sourceAndIncludePaths(languageSpec, SpoofaxConstants.LANG_SDF_NAME);
    final FileObject packSdfIncludesReplicateDir = paths.replicateDir().resolveFile("pack-sdf-includes");
    packSdfIncludesReplicateDir.delete(new AllFileSelector());
    final List<File> packSdfIncludePaths = Lists.newArrayList();
    for (FileObject path : sdfIncludePaths) {
        if (!path.exists()) {
            continue;
        }
        packSdfIncludePaths.add(resourceService.localFileUpdate(path, packSdfIncludesReplicateDir));
    }
    final Arguments packSdfArgs = config.sdfArgs();
    // SDF completions
    final String sdfCompletionModule = config.sdfName() + "-completion-insertions";
    @Nullable final File sdfCompletionFile;
    FileObject sdfCompletionFileCandidate = null;
    if (!sdf2tableVersion.javaBased) {
        sdfCompletionFileCandidate = paths.syntaxCompletionMainFile(sdfCompletionModule);
    } else {
        sdfCompletionFileCandidate = paths.syntaxCompletionMainFileNormalized(sdfCompletionModule);
    }
    if (sdfCompletionFileCandidate != null && sdfCompletionFileCandidate.exists()) {
        sdfCompletionFile = resourceService.localPath(sdfCompletionFileCandidate);
    } else {
        sdfCompletionFile = null;
    }
    // Meta-SDF
    final Iterable<FileObject> sdfRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_SDF_NAME);
    // final String sdfMetaModule = config.metaSdfName();
    List<String> sdfMetaModules = config.sdfMetaFiles();
    @Nullable final List<File> sdfMetaFiles = Lists.newArrayList();
    for (String sdfMetaModule : sdfMetaModules) {
        final FileObject sdfMetaFileCandidate;
        if (config.sdf2tableVersion().javaBased)
            sdfMetaFileCandidate = paths.syntaxSrcGenMainNormFile(sdfMetaModule);
        else
            sdfMetaFileCandidate = paths.findSyntaxMainFile(sdfRoots, sdfMetaModule);
        if (sdfMetaFileCandidate != null && sdfMetaFileCandidate.exists())
            sdfMetaFiles.add(resourceService.localPath(sdfMetaFileCandidate));
    }
    // Stratego
    final Boolean strEnabled = config.strEnabled();
    final String strModule = config.strategoName();
    final ArrayList<Supplier<Stratego2LibInfo>> str2libraries = new ArrayList<>();
    for (LanguageIdentifier sourceDep : sourceDeps) {
        @Nullable final ILanguageImpl sourceDepImpl = languageService.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 Iterable<FileObject> strRoots = languagePathService.sourcePaths(input.project(), SpoofaxConstants.LANG_STRATEGO_NAME);
    final FileObject strFileCandidate = config.strVersion().findStrMainFile(paths, strRoots, strModule);
    @Nullable final File strFile;
    if (strEnabled) {
        if (strFileCandidate != null && strFileCandidate.exists()) {
            strFile = resourceService.localPath(strFileCandidate);
        } else {
            final String fileExtension = config.strVersion() == StrategoVersion.v1 ? "str" : "str2";
            throw new MetaborgException("Cannot find Stratego main file '" + NameUtil.toJavaId(strModule.toLowerCase()) + "." + fileExtension + "'.");
        }
    } else {
        strFile = null;
    }
    final String strStratPkg = paths.strJavaTransPkg(config.identifier().id);
    final String strJavaStratPkg = paths.strJavaStratPkg(config.identifier().id);
    final FileObject strJavaStratFileCandidate = paths.strMainJavaStratFile(config.identifier().id);
    @Nullable final File strJavaStratFile;
    if (strJavaStratFileCandidate.exists()) {
        strJavaStratFile = resourceService.localPath(strJavaStratFileCandidate);
    } else {
        strJavaStratFile = null;
    }
    final StrategoFormat strFormat = config.strFormat();
    @Nullable final File strExternalJar;
    final String strExternalJarStr = config.strExternalJar();
    if (strEnabled && strExternalJarStr != null) {
        final FileObject strExternalJarLoc = resourceService.resolve(strExternalJarStr);
        if (!strExternalJarLoc.exists()) {
            throw new MetaborgException("External Stratego JAR at " + strExternalJarLoc + " does not exist");
        }
        strExternalJar = resourceService.localFile(strExternalJarLoc);
    } else {
        strExternalJar = null;
    }
    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");
    strjIncludesReplicateDir.delete(new AllFileSelector());
    final List<File> strjIncludeDirs = Lists.newArrayList();
    final List<File> strjIncludeFiles = Lists.newArrayList();
    for (FileObject path : strIncludePaths) {
        if (!path.exists()) {
            continue;
        }
        if (path.isFolder()) {
            strjIncludeDirs.add(resourceService.localFileUpdate(path, strjIncludesReplicateDir));
        }
        if (path.isFile()) {
            strjIncludeFiles.add(resourceService.localFileUpdate(path, strjIncludesReplicateDir));
        }
    }
    final Arguments strjArgs = config.strArgs();
    return new GenerateSourcesBuilder.Input(context, config.identifier(), sourceDeps, sdfEnabled, sdfModule, sdfFile, jsglrVersion, sdfVersion, sdf2tableVersion, checkOverlap, checkPriorities, sdfExternalDef, packSdfIncludePaths, packSdfArgs, sdfCompletionModule, sdfCompletionFile, sdfMetaModules, sdfMetaFiles, strEnabled, strFile, strStratPkg, strJavaStratPkg, strJavaStratFile, strFormat, strExternalJar, strExternalJarFlags, strjIncludeDirs, strjIncludeFiles, str2libraries, strjArgs, languageSpec.config().strShadowJar(), languageSpec.config().strVersion());
}
Also used : IExportConfig(org.metaborg.core.config.IExportConfig) MetaborgException(org.metaborg.core.MetaborgException) ArrayList(java.util.ArrayList) Stratego2LibInfo(mb.stratego.build.strincr.Stratego2LibInfo) BuildInput(org.metaborg.core.build.BuildInput) ISpoofaxLanguageSpec(org.metaborg.spoofax.meta.core.project.ISpoofaxLanguageSpec) ResourcePath(mb.resource.hierarchical.ResourcePath) AllFileSelector(org.apache.commons.vfs2.AllFileSelector) IExportVisitor(org.metaborg.core.config.IExportVisitor) LangDirExport(org.metaborg.core.config.LangDirExport) Supplier(mb.pie.api.Supplier) ValueSupplier(mb.pie.api.ValueSupplier) FileObject(org.apache.commons.vfs2.FileObject) LangFileExport(org.metaborg.core.config.LangFileExport) StrategoFormat(org.metaborg.spoofax.meta.core.config.StrategoFormat) ISpoofaxLanguageSpecConfig(org.metaborg.spoofax.meta.core.config.ISpoofaxLanguageSpecConfig) Arguments(org.metaborg.util.cmd.Arguments) JSGLRVersion(org.metaborg.core.config.JSGLRVersion) DynamicClassLoadingFacet(org.metaborg.spoofax.core.dynamicclassloading.DynamicClassLoadingFacet) LanguageIdentifier(org.metaborg.core.language.LanguageIdentifier) SdfVersion(org.metaborg.spoofax.meta.core.config.SdfVersion) ILanguageImpl(org.metaborg.core.language.ILanguageImpl) SpoofaxContext(org.metaborg.spoofax.meta.core.pluto.SpoofaxContext) ResourceExport(org.metaborg.core.config.ResourceExport) FSPath(mb.resource.fs.FSPath) Sdf2tableVersion(org.metaborg.core.config.Sdf2tableVersion) ILanguageComponent(org.metaborg.core.language.ILanguageComponent) File(java.io.File) Nullable(javax.annotation.Nullable)

Example 2 with ResourcePath

use of mb.resource.hierarchical.ResourcePath 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 3 with ResourcePath

use of mb.resource.hierarchical.ResourcePath in project spoofax by metaborg.

the class GenerateSourcesBuilder method splitOffLinkedLibrariesIncludeDirs.

/**
 * Copy oldArgs to newArgs, except for built-in libraries, which are split off and their names returned.
 * @return
 */
public static Arguments splitOffLinkedLibrariesIncludeDirs(Arguments oldArgs, Collection<IModuleImportService.ModuleIdentifier> builtinLibs, Collection<ResourcePath> includeDirs, String projectPath) {
    final Arguments newArgs = new Arguments();
    for (Iterator<Object> iterator = oldArgs.iterator(); iterator.hasNext(); ) {
        Object oldArg = iterator.next();
        if (oldArg.equals("-I")) {
            final Object nextOldArg = iterator.next();
            final Path nextOldArgPath;
            if (nextOldArg instanceof File) {
                nextOldArgPath = ((File) nextOldArg).toPath();
            } else if (nextOldArg instanceof String) {
                final String nextOldArgString = (String) nextOldArg;
                final Path path = Paths.get(nextOldArgString);
                if (path.isAbsolute()) {
                    nextOldArgPath = path;
                } else {
                    nextOldArgPath = Paths.get(projectPath, nextOldArgString);
                }
            } else {
                logger.error("-I argument is not a string or file? Ignoring this for import resolution: " + nextOldArg);
                newArgs.add(oldArg, nextOldArg);
                continue;
            }
            if (Files.exists(nextOldArgPath)) {
                includeDirs.add(new FSPath(nextOldArgPath));
            } else {
                logger.warn("-I argument '" + nextOldArgPath + "' does not exist, ignoring.");
            }
        } else if (oldArg.equals("-la")) {
            final Object nextOldArg = iterator.next();
            final String nextOldArgString = nextOldArg instanceof String ? (String) nextOldArg : nextOldArg.toString();
            @Nullable final BuiltinLibraryIdentifier libraryIdentifier = BuiltinLibraryIdentifier.fromString(nextOldArgString);
            if (libraryIdentifier == null) {
                // throw new MetaborgRuntimeException("Incremental compiler internal bug: missing support for custom pre-compiled libraries such as: " + nextOldArgString);
                newArgs.add(oldArg, nextOldArg);
                continue;
            }
            builtinLibs.add(libraryIdentifier);
        } else {
            newArgs.add(oldArg);
        }
    }
    return newArgs;
}
Also used : Path(java.nio.file.Path) ResourcePath(mb.resource.hierarchical.ResourcePath) FSPath(mb.resource.fs.FSPath) BuiltinLibraryIdentifier(mb.stratego.build.strincr.BuiltinLibraryIdentifier) Arguments(org.metaborg.util.cmd.Arguments) FSPath(mb.resource.fs.FSPath) File(java.io.File)

Example 4 with ResourcePath

use of mb.resource.hierarchical.ResourcePath 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)4 FSPath (mb.resource.fs.FSPath)4 ResourcePath (mb.resource.hierarchical.ResourcePath)4 Arguments (org.metaborg.util.cmd.Arguments)4 Path (java.nio.file.Path)3 ArrayList (java.util.ArrayList)3 Supplier (mb.pie.api.Supplier)3 HashSet (java.util.HashSet)2 Nullable (javax.annotation.Nullable)2 ExecException (mb.pie.api.ExecException)2 MixedSession (mb.pie.api.MixedSession)2 Pie (mb.pie.api.Pie)2 TopDownSession (mb.pie.api.TopDownSession)2 ValueSupplier (mb.pie.api.ValueSupplier)2 ResourceKey (mb.resource.ResourceKey)2 ModuleIdentifier (mb.stratego.build.strincr.ModuleIdentifier)2 Stratego2LibInfo (mb.stratego.build.strincr.Stratego2LibInfo)2 Message (mb.stratego.build.strincr.message.Message)2 FileObject (org.apache.commons.vfs2.FileObject)2 IExportConfig (org.metaborg.core.config.IExportConfig)2