Search in sources :

Example 1 with JsOutput

use of org.eclipse.ceylon.compiler.js.util.JsOutput in project ceylon by eclipse.

the class JsCompiler method finish.

/**
 * Closes all output writers and puts resulting artifacts in the output repo.
 */
protected int finish() throws IOException {
    int result = 0;
    String outDir = CeylonUtils.resolveRepoUrl(opts.getOutRepo());
    if (!isURL(outDir)) {
        File root = new File(outDir);
        if (root.exists()) {
            if (!(root.isDirectory() && root.canWrite())) {
                logger.error("Cannot write to " + root + ". Stop.");
                result = 1;
            }
        } else {
            if (!FileUtil.mkdirs(root)) {
                logger.error("Cannot create " + root + ". Stop.");
                result = 1;
            }
        }
    }
    for (Map.Entry<Module, JsOutput> entry : output.entrySet()) {
        JsOutput jsout = entry.getValue();
        if (!compilingLanguageModule) {
            jsout.publishUnsharedDeclarations(names);
        }
        if (opts.isModulify()) {
            jsout.closeWrapper();
        }
        String moduleName = entry.getKey().getNameAsString();
        String moduleVersion = entry.getKey().getVersion();
        if (opts.getDiagnosticListener() != null)
            opts.getDiagnosticListener().moduleCompiled(moduleName, moduleVersion);
        // Create the JS file
        final File jsart = jsout.close();
        final File modart = jsout.getModelFile();
        if (entry.getKey().isDefaultModule()) {
            logger.info("Created module " + moduleName);
        } else if (!compilingLanguageModule) {
            logger.info("Created module " + moduleName + "/" + moduleVersion);
        }
        if (compilingLanguageModule) {
            ArtifactContext artifact = new ArtifactContext(null, "delete", "me", ArtifactContext.JS);
            artifact.setForceOperation(true);
            outRepo.putArtifact(artifact, jsart);
        } else {
            final ArtifactContext artifact = new ArtifactContext(null, moduleName, moduleVersion, ArtifactContext.JS);
            artifact.setForceOperation(true);
            outRepo.putArtifact(artifact, jsart);
            final ArtifactContext martifact = new ArtifactContext(null, moduleName, moduleVersion, ArtifactContext.JS_MODEL);
            martifact.setForceOperation(true);
            outRepo.putArtifact(martifact, modart);
            // js file signature
            ShaSigner.signArtifact(outRepo, artifact, jsart, logger);
            ShaSigner.signArtifact(outRepo, martifact, modart, logger);
            // Create the src archive
            if (opts.isGenerateSourceArchive()) {
                ArtifactCreator sac = CeylonUtils.makeSourceArtifactCreator(outRepo, opts.getSrcDirs(), moduleName, moduleVersion, opts.hasVerboseFlag("cmr"), logger);
                sac.copy(FileUtil.filesToPathList(jsout.getSources()));
            }
            if (resFiles != null && !resFiles.isEmpty()) {
                ArtifactCreator sac = CeylonUtils.makeResourceArtifactCreator(outRepo, opts.getSrcDirs(), opts.getResourceDirs(), opts.getResourceRootName(), moduleName, moduleVersion, opts.hasVerboseFlag("cmr"), logger);
                sac.copy(FileUtil.filesToPathList(filterForModule(resFiles, opts.getResourceDirs(), moduleName)));
            }
            if (!entry.getKey().isDefaultModule()) {
                String npmdesc = new NpmDescriptorGenerator(entry.getKey(), opts.isGenerateSourceArchive(), resFiles != null && !resFiles.isEmpty()).generateDescriptor();
                File npmfile = File.createTempFile("npm", "json");
                try {
                    try (FileWriter fw = new FileWriter(npmfile)) {
                        fw.write(npmdesc);
                    }
                    final ArtifactContext npmArtifact = new ArtifactContext(null, moduleName, moduleVersion, ArtifactContext.NPM_DESCRIPTOR);
                    npmArtifact.setForceOperation(true);
                    outRepo.putArtifact(npmArtifact, npmfile);
                } finally {
                    npmfile.delete();
                }
            }
        }
        FileUtil.deleteQuietly(jsart);
        if (modart != null) {
            FileUtil.deleteQuietly(modart);
        }
    }
    return result;
}
Also used : JsOutput(org.eclipse.ceylon.compiler.js.util.JsOutput) ArtifactCreator(org.eclipse.ceylon.cmr.api.ArtifactCreator) FileWriter(java.io.FileWriter) ArtifactContext(org.eclipse.ceylon.cmr.api.ArtifactContext) NpmDescriptorGenerator(org.eclipse.ceylon.compiler.js.util.NpmDescriptorGenerator) Module(org.eclipse.ceylon.model.typechecker.model.Module) VirtualFile(org.eclipse.ceylon.compiler.typechecker.io.VirtualFile) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap)

Example 2 with JsOutput

use of org.eclipse.ceylon.compiler.js.util.JsOutput in project ceylon by eclipse.

the class JsCompiler method compileUnit.

/**
 * Compile one phased unit.
 */
private int compileUnit(PhasedUnit pu, JsIdentifierNames names) throws IOException {
    if (opts.isVerbose()) {
        logger.debug("Compiling " + pu.getUnitFile().getPath() + " to JS");
    }
    JsOutput jsout = getOutput(pu);
    MissingNativeVisitor mnv = new JsMissingNativeVisitor(opts.getCwd());
    pu.getCompilationUnit().visit(mnv);
    GenerateJsVisitor jsv = new GenerateJsVisitor(this, jsout, opts, names, pu.getTokens());
    pu.getCompilationUnit().visit(jsv);
    pu.getCompilationUnit().visit(errorVisitor);
    return jsv.getExitCode();
}
Also used : JsOutput(org.eclipse.ceylon.compiler.js.util.JsOutput) MissingNativeVisitor(org.eclipse.ceylon.compiler.typechecker.analyzer.MissingNativeVisitor)

Example 3 with JsOutput

use of org.eclipse.ceylon.compiler.js.util.JsOutput in project ceylon by eclipse.

the class JsCompiler method generate.

/**
 * Compile all the phased units in the typechecker.
 * @return true is compilation was successful (0 errors/warnings), false otherwise.
 */
public boolean generate() throws IOException {
    errorVisitor.clear();
    errCount = 0;
    output.clear();
    try {
        if (opts.isVerbose()) {
            logger.debug("Generating metamodel...");
        }
        List<PhasedUnit> typecheckerPhasedUnits = tc.getPhasedUnits().getPhasedUnits();
        List<PhasedUnit> phasedUnits = new ArrayList<>(typecheckerPhasedUnits.size());
        for (PhasedUnit pu : typecheckerPhasedUnits) {
            if (srcFiles == null) {
                phasedUnits.add(pu);
            } else {
                File path = getFullPath(pu);
                if (srcFiles.contains(path)) {
                    phasedUnits.add(pu);
                }
            }
        }
        boolean generatedCode = false;
        // First generate the metamodel
        final Module defmod = tc.getContext().getModules().getDefaultModule();
        for (PhasedUnit pu : phasedUnits) {
            // #416 default module with packages
            Module mod = pu.getPackage().getModule();
            if (mod.getVersion() == null && !mod.isDefaultModule()) {
                // Switch with the default module
                for (org.eclipse.ceylon.model.typechecker.model.Package pkg : mod.getPackages()) {
                    defmod.getPackages().add(pkg);
                    pkg.setModule(defmod);
                }
            }
            EnumSet<Warning> suppressedWarnings = opts.getSuppressWarnings();
            if (suppressedWarnings == null)
                suppressedWarnings = EnumSet.noneOf(Warning.class);
            pu.getCompilationUnit().visit(new WarningSuppressionVisitor<>(Warning.class, suppressedWarnings));
            // Perform capture analysis
            for (org.eclipse.ceylon.model.typechecker.model.Declaration d : pu.getDeclarations()) {
                if (d instanceof TypedDeclaration && d instanceof org.eclipse.ceylon.model.typechecker.model.Setter == false) {
                    pu.getCompilationUnit().visit(new ValueVisitor((TypedDeclaration) d));
                }
            }
            pu.getCompilationUnit().visit(getOutput(pu).mmg);
            if (opts.hasVerboseFlag("ast")) {
                if (opts.getOutWriter() == null) {
                    logger.debug(pu.getCompilationUnit().toString());
                } else {
                    opts.getOutWriter().write(pu.getCompilationUnit().toString());
                    opts.getOutWriter().write('\n');
                }
            }
        }
        // Then write it out and output the reference in the module file
        names = new JsIdentifierNames(this);
        if (!compilingLanguageModule) {
            for (Map.Entry<Module, JsOutput> e : output.entrySet()) {
                e.getValue().encodeModel(names);
            }
        }
        // Output all the require calls for any imports
        final Visitor importVisitor = new Visitor() {

            public void visit(Tree.Import that) {
                ImportableScope scope = that.getImportMemberOrTypeList().getImportList().getImportedScope();
                Module _m = that.getUnit().getPackage().getModule();
                if (scope instanceof Package) {
                    Package pkg = (Package) scope;
                    Module om = pkg.getModule();
                    if (!om.equals(_m) && (!om.isNative() || om.getNativeBackends().supports(Backend.JavaScript))) {
                        Module impmod = ((Package) scope).getModule();
                        if (impmod instanceof NpmAware && ((NpmAware) impmod).getNpmPath() != null) {
                            output.get(_m).requireFromNpm(impmod, names);
                        } else {
                            output.get(_m).require(impmod, names);
                        }
                    }
                }
            }

            public void visit(Tree.ImportModule that) {
                if (that.getImportPath() != null && that.getImportPath().getModel() instanceof Module) {
                    Module m = (Module) that.getImportPath().getModel();
                    // Binary version check goes here now
                    int binMajorVersion = m.getJsMajor();
                    int binMinorVersion = m.getJsMinor();
                    if (m.getJsMajor() == 0) {
                        // Check if it's something we're compiling
                        for (PhasedUnit pu : tc.getPhasedUnits().getPhasedUnits()) {
                            if (pu.getPackage() != null && pu.getPackage().getModule() == m) {
                                m.setJsMajor(Versions.JS_BINARY_MAJOR_VERSION);
                                m.setJsMinor(Versions.JS_BINARY_MINOR_VERSION);
                                binMajorVersion = Versions.JS_BINARY_MAJOR_VERSION;
                                binMinorVersion = Versions.JS_BINARY_MINOR_VERSION;
                                break;
                            }
                        }
                        if (m.getJsMajor() == 0) {
                            // Load the module (most likely we're in the IDE if we need to do this)
                            ArtifactContext ac = new ArtifactContext(null, m.getNameAsString(), m.getVersion(), ArtifactContext.JS_MODEL);
                            ac.setIgnoreDependencies(true);
                            ac.setThrowErrorIfMissing(false);
                            ArtifactResult ar = tc.getContext().getRepositoryManager().getArtifactResult(ac);
                            if (ar == null) {
                                return;
                            }
                            File js = ar.artifact();
                            if (js != null) {
                                Map<String, Object> json = JsModuleSourceMapper.loadJsonModel(js);
                                String binVersion = json.get("$mod-bin").toString();
                                int p = binVersion.indexOf('.');
                                binMajorVersion = Integer.valueOf(binVersion.substring(0, p));
                                binMinorVersion = Integer.valueOf(binVersion.substring(p + 1));
                            }
                        }
                    }
                    if (!Versions.isJsBinaryVersionSupported(binMajorVersion, binMinorVersion)) {
                        that.addError("version '" + m.getVersion() + "' of module '" + m.getNameAsString() + "' was compiled by an incompatible version of the compiler (binary version " + binMajorVersion + "." + binMinorVersion + " of module is not compatible with binary version " + Versions.JS_BINARY_MAJOR_VERSION + "." + Versions.JS_BINARY_MINOR_VERSION + " of this compiler)");
                    }
                }
            }
        };
        for (PhasedUnit pu : phasedUnits) {
            pu.getCompilationUnit().visit(importVisitor);
        }
        // Then generate the JS code
        List<PhasedUnit> pkgs = new ArrayList<>(4);
        if (srcFiles == null && !phasedUnits.isEmpty()) {
            for (PhasedUnit pu : phasedUnits) {
                if ("module.ceylon".equals(pu.getUnitFile().getName())) {
                    final int t = compileUnit(pu);
                    generatedCode = true;
                    if (t != 0) {
                        return false;
                    }
                }
            }
            for (PhasedUnit pu : phasedUnits) {
                if ("package.ceylon".equals(pu.getUnitFile().getName())) {
                    pkgs.add(pu);
                    continue;
                } else if ("module.ceylon".equals(pu.getUnitFile().getName())) {
                    continue;
                }
                final int t = compileUnit(pu);
                generatedCode = true;
                if (t == 1) {
                    return false;
                } else if (t == 2) {
                    break;
                }
            }
        } else if (srcFiles != null && !srcFiles.isEmpty() && // For the specific case of the Stitcher
        !typecheckerPhasedUnits.isEmpty()) {
            for (PhasedUnit pu : phasedUnits) {
                if ("module.ceylon".equals(pu.getUnitFile().getName())) {
                    final int t = compileUnit(pu);
                    generatedCode = true;
                    if (t != 0) {
                        return false;
                    }
                }
            }
            for (File path : srcFiles) {
                if (path.getPath().endsWith(ArtifactContext.JS)) {
                    // Just output the file
                    File dir = path.getParentFile();
                    PhasedUnit lastUnit = phasedUnits.isEmpty() ? typecheckerPhasedUnits.get(0) : phasedUnits.get(0);
                    for (PhasedUnit pu : phasedUnits) {
                        if (pu.getUnitFile().getPath().startsWith(dir.getPath())) {
                            lastUnit = pu;
                            break;
                        }
                    }
                    final JsOutput lastOut = getOutput(lastUnit);
                    VirtualFile vpath = findFile(path);
                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(vpath.getInputStream(), opts.getEncoding()))) {
                        String line = null;
                        while ((line = reader.readLine()) != null) {
                            if (opts.isMinify()) {
                                line = line.trim();
                                if (!opts.isComment() && line.startsWith("//") && !line.contains("*/")) {
                                    continue;
                                }
                            }
                            if (line.length() == 0) {
                                continue;
                            }
                            lastOut.getWriter().write(line);
                            lastOut.getWriter().write('\n');
                        }
                    } finally {
                        lastOut.addSource(path);
                    }
                    generatedCode = true;
                } else {
                    // Find the corresponding compilation unit
                    for (PhasedUnit pu : phasedUnits) {
                        File unitFile = getFullPath(pu);
                        if (path.equals(unitFile)) {
                            if (path.getName().equals("package.ceylon")) {
                                pkgs.add(pu);
                                continue;
                            } else if (path.getName().equals("module.ceylon")) {
                                continue;
                            }
                            final int t = compileUnit(pu);
                            generatedCode = true;
                            if (t == 1) {
                                return false;
                            } else if (t == 2) {
                                break;
                            }
                        }
                    }
                }
            }
            if (resFiles != null) {
                for (Map.Entry<Module, JsOutput> entry : output.entrySet()) {
                    Module module = entry.getKey();
                    final JsOutput lastOut = getOutput(module);
                    for (File file : filterForModule(resFiles, opts.getResourceDirs(), module.getNameAsString())) {
                        String type = Files.probeContentType(file.toPath());
                        String fileName = file.getName();
                        boolean isResourceFile = fileName.endsWith(".properties") || fileName.endsWith(".txt");
                        if (isResourceFile || type != null && type.startsWith("text")) {
                            Writer writer = lastOut.getWriter();
                            writer.write("ex$.");
                            writer.write(resourceKey(module, file));
                            writer.write("=\"");
                            Pattern pattern = Pattern.compile("\\\\|\\t|\\r|\\f|\\n");
                            try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), opts.getEncoding()))) {
                                String line = null;
                                while ((line = reader.readLine()) != null) {
                                    if (isResourceFile && opts.isMinify()) {
                                        line = line.trim();
                                        if (line.length() == 0) {
                                            continue;
                                        }
                                        if (!opts.isComment() && line.startsWith("#")) {
                                            continue;
                                        }
                                    }
                                    StringBuffer result = new StringBuffer();
                                    Matcher matcher = pattern.matcher(line);
                                    while (matcher.find()) {
                                        String escaped;
                                        switch(matcher.group(0)) {
                                            case "\\":
                                                escaped = "\\\\\\\\";
                                                break;
                                            case "\t":
                                                escaped = "\\\\t";
                                                break;
                                            case "\r":
                                                escaped = "\\\\r";
                                                break;
                                            case "\f":
                                                escaped = "\\\\f";
                                                break;
                                            case "\n":
                                                escaped = "\\\\n";
                                                break;
                                            default:
                                                throw new IllegalStateException();
                                        }
                                        matcher.appendReplacement(result, escaped);
                                    }
                                    matcher.appendTail(result);
                                    writer.write(result.toString());
                                    if (reader.ready()) {
                                        writer.write("\\n");
                                    }
                                }
                            }
                            writer.write("\";\n");
                            generatedCode = true;
                        }
                    }
                }
            }
        }
        for (PhasedUnit pu : pkgs) {
            final int t = compileUnit(pu);
            generatedCode = true;
            if (t == 1) {
                return false;
            } else if (t == 2) {
                break;
            }
        }
        if (!generatedCode) {
            logger.error("No source units found to compile");
            exitCode = 2;
        }
    } finally {
        if (exitCode == 0) {
            exitCode = finish();
        }
    }
    return errCount == 0 && exitCode == 0;
}
Also used : VirtualFile(org.eclipse.ceylon.compiler.typechecker.io.VirtualFile) Warning(org.eclipse.ceylon.compiler.typechecker.analyzer.Warning) WarningSuppressionVisitor(org.eclipse.ceylon.compiler.typechecker.util.WarningSuppressionVisitor) Visitor(org.eclipse.ceylon.compiler.typechecker.tree.Visitor) MissingNativeVisitor(org.eclipse.ceylon.compiler.typechecker.analyzer.MissingNativeVisitor) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) ArtifactContext(org.eclipse.ceylon.cmr.api.ArtifactContext) PhasedUnit(org.eclipse.ceylon.compiler.typechecker.context.PhasedUnit) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) ImportableScope(org.eclipse.ceylon.model.typechecker.model.ImportableScope) Pattern(java.util.regex.Pattern) Package(org.eclipse.ceylon.model.typechecker.model.Package) JsIdentifierNames(org.eclipse.ceylon.compiler.js.util.JsIdentifierNames) InputStreamReader(java.io.InputStreamReader) FileInputStream(java.io.FileInputStream) ArtifactResult(org.eclipse.ceylon.model.cmr.ArtifactResult) NpmAware(org.eclipse.ceylon.compiler.js.loader.NpmAware) JsOutput(org.eclipse.ceylon.compiler.js.util.JsOutput) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) BufferedReader(java.io.BufferedReader) Package(org.eclipse.ceylon.model.typechecker.model.Package) Module(org.eclipse.ceylon.model.typechecker.model.Module) VirtualFile(org.eclipse.ceylon.compiler.typechecker.io.VirtualFile) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) Writer(java.io.Writer) FileWriter(java.io.FileWriter)

Example 4 with JsOutput

use of org.eclipse.ceylon.compiler.js.util.JsOutput in project ceylon by eclipse.

the class Stitcher method encodeModel.

private static int encodeModel(final File moduleFile) throws IOException {
    final String name = moduleFile.getName();
    final File file = new File(moduleFile.getParentFile(), name.substring(0, name.length() - 3) + ArtifactContext.JS_MODEL);
    System.out.println("Generating language module compile-time model in JSON...");
    TypeCheckerBuilder tcb = new TypeCheckerBuilder().usageWarnings(false);
    tcb.addSrcDirectory(clSrcDir);
    TypeChecker tc = tcb.getTypeChecker();
    tc.process(true);
    MetamodelVisitor mmg = null;
    final ErrorCollectingVisitor errVisitor = new ErrorCollectingVisitor(tc);
    for (PhasedUnit pu : tc.getPhasedUnits().getPhasedUnits()) {
        pu.getCompilationUnit().visit(errVisitor);
        if (errVisitor.getErrorCount() > 0) {
            errVisitor.printErrors(false, false);
            System.out.println("errors in the language module " + pu.getCompilationUnit().getLocation());
            return 1;
        }
        if (mmg == null) {
            mmg = new MetamodelVisitor(pu.getPackage().getModule());
        }
        pu.getCompilationUnit().visit(mmg);
    }
    mod = tc.getPhasedUnits().getPhasedUnits().get(0).getPackage().getModule();
    try (FileWriter writer = new FileWriter(file)) {
        JsCompiler.beginWrapper(writer);
        writer.write("ex$.$CCMM$=");
        ModelEncoder.encodeModel(mmg.getModel(), writer);
        writer.write(";\n");
        final JsOutput jsout = new JsOutput(mod, true) {

            @Override
            public Writer getWriter() throws IOException {
                return writer;
            }
        };
        jsout.outputFile(new File(LANGMOD_JS_SRC, "MODEL.js"));
        JsCompiler.endWrapper(writer);
    } finally {
        ShaSigner.sign(file, new JsJULLogger(), true);
    }
    final File npmFile = new File(moduleFile.getParentFile(), ArtifactContext.NPM_DESCRIPTOR);
    try (FileWriter writer = new FileWriter(npmFile)) {
        String npmdesc = new NpmDescriptorGenerator(mod, true, false).generateDescriptor();
        writer.write(npmdesc);
    }
    return 0;
}
Also used : JsOutput(org.eclipse.ceylon.compiler.js.util.JsOutput) JsJULLogger(org.eclipse.ceylon.compiler.js.util.JsJULLogger) TypeChecker(org.eclipse.ceylon.compiler.typechecker.TypeChecker) MetamodelVisitor(org.eclipse.ceylon.compiler.js.loader.MetamodelVisitor) FileWriter(java.io.FileWriter) NpmDescriptorGenerator(org.eclipse.ceylon.compiler.js.util.NpmDescriptorGenerator) TypeCheckerBuilder(org.eclipse.ceylon.compiler.typechecker.TypeCheckerBuilder) File(java.io.File) PhasedUnit(org.eclipse.ceylon.compiler.typechecker.context.PhasedUnit)

Example 5 with JsOutput

use of org.eclipse.ceylon.compiler.js.util.JsOutput in project ceylon by eclipse.

the class JsCompiler method getOutput.

private JsOutput getOutput(Module mod) throws IOException {
    JsOutput jsout = output.get(mod);
    if (jsout == null) {
        jsout = newJsOutput(mod);
        output.put(mod, jsout);
        if (opts.isModulify()) {
            jsout.openWrapper();
        }
    }
    return jsout;
}
Also used : JsOutput(org.eclipse.ceylon.compiler.js.util.JsOutput)

Aggregations

JsOutput (org.eclipse.ceylon.compiler.js.util.JsOutput)6 File (java.io.File)4 FileWriter (java.io.FileWriter)3 HashMap (java.util.HashMap)2 Map (java.util.Map)2 ArtifactContext (org.eclipse.ceylon.cmr.api.ArtifactContext)2 JsJULLogger (org.eclipse.ceylon.compiler.js.util.JsJULLogger)2 NpmDescriptorGenerator (org.eclipse.ceylon.compiler.js.util.NpmDescriptorGenerator)2 MissingNativeVisitor (org.eclipse.ceylon.compiler.typechecker.analyzer.MissingNativeVisitor)2 PhasedUnit (org.eclipse.ceylon.compiler.typechecker.context.PhasedUnit)2 VirtualFile (org.eclipse.ceylon.compiler.typechecker.io.VirtualFile)2 Module (org.eclipse.ceylon.model.typechecker.model.Module)2 BufferedReader (java.io.BufferedReader)1 FileInputStream (java.io.FileInputStream)1 FileOutputStream (java.io.FileOutputStream)1 InputStreamReader (java.io.InputStreamReader)1 OutputStreamWriter (java.io.OutputStreamWriter)1 Writer (java.io.Writer)1 ArrayList (java.util.ArrayList)1 Matcher (java.util.regex.Matcher)1