Package com.redhat.ceylon.compiler.js

Source Code of com.redhat.ceylon.compiler.js.Stitcher

package com.redhat.ceylon.compiler.js;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import com.redhat.ceylon.cmr.api.ArtifactContext;
import com.redhat.ceylon.cmr.ceylon.CeylonUtils;
import com.redhat.ceylon.cmr.impl.ShaSigner;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.compiler.Options;
import com.redhat.ceylon.compiler.loader.ModelEncoder;
import com.redhat.ceylon.compiler.typechecker.TypeChecker;
import com.redhat.ceylon.compiler.typechecker.TypeCheckerBuilder;
import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit;
import com.redhat.ceylon.compiler.typechecker.tree.Message;

/** A simple program that takes the main JS module file and replaces #include markers with the contents of other files.
*
* @author Enrique Zamudio
*/
public class Stitcher {

    private static TypeCheckerBuilder langmodtc;
    private static Path tmpDir;
   
    public static final File clSrcDir = new File("../ceylon.language/src/ceylon/language/");
    public static final File LANGMOD_JS_SRC = new File("../ceylon.language/runtime-js");
    public static final File LANGMOD_JS_SRC2 = new File("../ceylon.language/runtime-js/ceylon/language");

    private static int compileLanguageModule(final String line, Writer writer)
            throws IOException {
        File clsrcTmpDir = Files.createTempDirectory(tmpDir, "clsrc").toFile();
        final File tmpout = new File(clsrcTmpDir, Constants.DEFAULT_MODULE_DIR);
        tmpout.mkdir();
        final Options opts = new Options().addRepo("build/runtime").comment(false).optimize(true)
                .outRepo(tmpout.getAbsolutePath()).modulify(false).minify(true);

        //Typecheck the whole language module
        if (langmodtc == null) {
            langmodtc = new TypeCheckerBuilder().addSrcDirectory(clSrcDir.getParentFile().getParentFile())
                    .addSrcDirectory(LANGMOD_JS_SRC)
                    .encoding("UTF-8");
            langmodtc.setRepositoryManager(CeylonUtils.repoManager().systemRepo(opts.getSystemRepo())
                    .userRepos(opts.getRepos()).outRepo(opts.getOutRepo()).buildManager());
        }
        final File mod2 = new File(LANGMOD_JS_SRC2, "module.ceylon");
        if (!mod2.exists()) {
            try (FileWriter w2 = new FileWriter(mod2);
                    FileReader r2 = new FileReader(new File(clSrcDir, "module.ceylon"))) {
                char[] c = new char[512];
                int r = r2.read(c);
                while (r != -1) {
                    w2.write(c, 0, r);
                    r = r2.read(c);
                }
                mod2.deleteOnExit();
            } finally {
            }
        }
        final TypeChecker tc = langmodtc.getTypeChecker();
        tc.process();
        if (tc.getErrors() > 0) {
            return 1;
        }

        //Compile these files
        final List<File> includes = new ArrayList<File>();
        for (String filename : line.split(",")) {
            final boolean isJsSrc = filename.trim().endsWith(".js");
            final File src = new File(isJsSrc ? LANGMOD_JS_SRC : clSrcDir,
                    isJsSrc ? filename.trim() :
                    String.format("%s.ceylon", filename.trim()));
            if (src.exists() && src.isFile() && src.canRead()) {
                includes.add(src);
            } else {
                final File src2 = new File(LANGMOD_JS_SRC2, String.format("%s.ceylon", filename.trim()));
                if (src2.exists() && src2.isFile() && src2.canRead()) {
                    includes.add(src2);
                } else {
                    throw new IllegalArgumentException("Invalid Ceylon language module source " + src + " or " + src2);
                }
            }
        }
        //Compile only the files specified in the line
        //Set this before typechecking to share some decls that otherwise would be private
        JsCompiler.compilingLanguageModule=true;
        JsCompiler jsc = new JsCompiler(tc, opts).stopOnErrors(false);
        jsc.setSourceFiles(includes);
        jsc.generate();
        JsCompiler.compilingLanguageModule=false;
        File compsrc = new File(tmpout, "delete/me/delete-me.js");
        if (compsrc.exists() && compsrc.isFile() && compsrc.canRead()) {
            try (BufferedReader jsr = new BufferedReader(new FileReader(compsrc))) {
                String jsline = null;
                while ((jsline = jsr.readLine()) != null) {
                    if (!jsline.contains("=require('")) {
                        writer.write(jsline);
                        writer.write("\n");
                    }
                }
            } finally {
                compsrc.delete();
            }
        } else {
            System.out.println("Can't find generated js for language module in " + compsrc.getAbsolutePath());
            return 1;
        }
        return 0;
    }

    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.getParentFile().getParentFile());
        TypeChecker tc = tcb.getTypeChecker();
        tc.process();
        MetamodelVisitor mmg = null;
        for (PhasedUnit pu : tc.getPhasedUnits().getPhasedUnits()) {
            if (!pu.getCompilationUnit().getErrors().isEmpty()) {
                System.out.println("whoa, errors in the language module "
                        + pu.getCompilationUnit().getLocation());
                for (Message err : pu.getCompilationUnit().getErrors()) {
                    System.out.println(err.getMessage());
                }
            }
            if (mmg == null) {
                mmg = new MetamodelVisitor(pu.getPackage().getModule());
            }
            pu.getCompilationUnit().visit(mmg);
        }
        try (FileWriter writer = new FileWriter(file)) {
            JsCompiler.beginWrapper(writer);
            writer.write("ex$.$CCMM$=");
            ModelEncoder.encodeModel(mmg.getModel(), writer);
            writer.write(";\n");
            int exitCode = compileLanguageModule("MODEL.js", writer);
            if (exitCode != 0) {
                return exitCode;
            }
            JsCompiler.endWrapper(writer);
        } finally {
            ShaSigner.sign(file, new JsJULLogger(), true);
        }
        return 0;
    }

    private static int stitch(File infile, Writer writer, String version) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(infile), "UTF-8"));
        try {
            String line = null;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0) {
                    if (line.equals("//#METAMODEL")) {
                        writer.write("var _CTM$;function $CCMM$(){if (_CTM$===undefined)_CTM$=require('");
                        writer.write("ceylon/language/");
                        writer.write(version);
                        writer.write("/ceylon.language-");
                        writer.write(version);
                        writer.write("-model");
                        writer.write("').$CCMM$;return _CTM$;}\n");
                        writer.write("ex$.$CCMM$=$CCMM$;");
                    } else if (line.startsWith("//#COMPILE ")) {
                        final String sourceFiles = line.substring(11);
                        System.out.println("Compiling language module sources: " + sourceFiles);
                        int exitCode = compileLanguageModule(sourceFiles, writer);
                        if (exitCode != 0) {
                            return exitCode;
                        }
                    } else if (!line.endsWith("//IGNORE")) {
                        writer.write(line);
                        writer.write("\n");
                    }
                }
            }
        } finally {
            if (reader != null) reader.close();
        }
        return 0;
    }

    public static void main(String[] args) throws IOException {
        if (args.length < 2) {
            System.err.println("This program requires 3 arguments to run:");
            System.err.println("1. The path to the main JS file");
            System.err.println("2. The path of the resulting JS file");
            System.exit(1);
            return;
        }
        int exitCode = 0;
        tmpDir = Files.createTempDirectory("ceylon-jsstitcher-");
        try {
            File infile = new File(args[0]);
            if (infile.exists() && infile.isFile() && infile.canRead()) {
                File outfile = new File(args[1]);
                if (!outfile.getParentFile().exists()) {
                    outfile.getParentFile().mkdirs();
                }
                exitCode = encodeModel(outfile);
                if (exitCode == 0) {
                    final int p0 = args[1].indexOf(".language-");
                    final String version = args[1].substring(p0+10,args[1].length()-3);
                    try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(outfile), "UTF-8")) {
                        exitCode = stitch(infile, writer, version);
                    } finally {
                        ShaSigner.sign(outfile, new JsJULLogger(), true);
                    }
                }
            } else {
                System.err.println("Input file is invalid: " + infile);
                exitCode = 2;
            }
        } finally {
            FileUtil.deleteQuietly(tmpDir.toFile());
        }
        if (exitCode != 0) {
            System.exit(exitCode);
        }
    }
}
TOP

Related Classes of com.redhat.ceylon.compiler.js.Stitcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.