Package com.redhat.ceylon.compiler.js

Source Code of com.redhat.ceylon.compiler.js.CeylonCompileJsTool$AppendableWriter

package com.redhat.ceylon.compiler.js;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.redhat.ceylon.cmr.api.RepositoryManager;
import com.redhat.ceylon.cmr.ceylon.OutputRepoUsingTool;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.FileUtil;
import com.redhat.ceylon.common.config.DefaultToolOptions;
import com.redhat.ceylon.common.tool.Argument;
import com.redhat.ceylon.common.tool.Description;
import com.redhat.ceylon.common.tool.Option;
import com.redhat.ceylon.common.tool.OptionArgument;
import com.redhat.ceylon.common.tool.ParsedBy;
import com.redhat.ceylon.common.tool.RemainingSections;
import com.redhat.ceylon.common.tool.StandardArgumentParsers;
import com.redhat.ceylon.common.tool.Summary;
import com.redhat.ceylon.common.tools.SourceArgumentsResolver;
import com.redhat.ceylon.compiler.Options;
import com.redhat.ceylon.compiler.loader.JsModuleManagerFactory;
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.io.VirtualFile;

@Summary("Compiles Ceylon source code to JavaScript and directly produces " +
        "module and source archives in a module repository")
@RemainingSections(
        OutputRepoUsingTool.DOCSECTION_CONFIG_COMPILER +
        "\n\n" +
        OutputRepoUsingTool.DOCSECTION_REPOSITORIES)
public class CeylonCompileJsTool extends OutputRepoUsingTool {

    public static class AppendableWriter extends Writer {

        private Appendable out;

        public AppendableWriter(Appendable out) {
            this.out = out;
        }

        @Override
        public void close() throws IOException {
        }

        @Override
        public void flush() throws IOException {
        }

        @Override
        public void write(char[] cbuf, int off, int len) throws IOException {
            out.append(new String(cbuf, off, len));
        }

        @Override
        public void write(String str) throws IOException {
            out.append(str);
        }
    }

    private boolean profile = false;
    private boolean optimize = true;
    private boolean modulify = true;
    private boolean indent = true;
    private boolean comments = false;
    private boolean skipSrc = false;

    private String encoding;

    private List<File> roots = DefaultToolOptions.getCompilerSourceDirs();
    private List<File> resources = DefaultToolOptions.getCompilerResourceDirs();
    private String resourceRootName = DefaultToolOptions.getCompilerResourceRootName();
    private List<String> files = Arrays.asList("*");
    private DiagnosticListener diagnosticListener;
    private boolean throwOnError;

    public CeylonCompileJsTool() {
        super(CeylonCompileJsMessages.RESOURCE_BUNDLE);
    }

    @OptionArgument(shortName='E', argumentName="encoding")
    @Description("Sets the encoding used for reading source files (default: platform-specific)")
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getEncoding(){
        return encoding;
    }

    @Option
    @Description("Time the compilation phases (results are printed to standard error)")
    public void setProfile(boolean profile) {
        this.profile = profile;
    }

    @Option
    @Description("Create lexical scope-style JS code")
    public void setLexicalScopeStyle(boolean flag) {
        this.optimize = !flag;
    }

    @Option(longName="no-module")
    @Description("Do **not** wrap generated code as CommonJS module")
    public void setNoModulify(boolean nomodulify) {
        this.modulify = !nomodulify;
    }

    @Option
    @Description("Do **not** indent code")
    public void setNoIndent(boolean noindent) {
        this.indent = !noindent;
    }

    @Option
    @Description("Equivalent to `--no-indent` `--no-comments`")
    public void setCompact(boolean compact) {
        this.setNoIndent(compact);
        this.setNoComments(compact);
    }

    @Option
    @Description("Do **not** generate any comments")
    public void setNoComments(boolean nocomments) {
        this.comments = !nocomments;
    }

    public List<String> getFilesAsStrings(final List<File> files) {
        if (files != null) {
            List<String> result = new ArrayList<>(files.size());
            for (File f : files) {
                result.add(f.getPath());
            }
            return result;
        } else {
            return Collections.emptyList();
        }
    }

    @OptionArgument(shortName='s', longName="src", argumentName="dirs")
    @ParsedBy(StandardArgumentParsers.PathArgumentParser.class)
    @Description("Path to source files. " +
        "Can be specified multiple times; you can also specify several " +
        "paths separated by your operating system's `PATH` separator." +
            " (default: `./source`)")
    public void setSrc(List<File> src) {
        roots = src;
    }

    @OptionArgument(longName="source", argumentName="dirs")
    @ParsedBy(StandardArgumentParsers.PathArgumentParser.class)
    @Description("An alias for `--src`" +
            " (default: `./source`)")
    public void setSource(List<File> source) {
        setSrc(source);
    }

    @OptionArgument(shortName='r', longName="resource", argumentName="dirs")
    @ParsedBy(StandardArgumentParsers.PathArgumentParser.class)
    @Description("Path to directory containing resource files. " +
            "Can be specified multiple times; you can also specify several " +
            "paths separated by your operating system's `PATH` separator." +
            " (default: `./resource`)")
    public void setResource(List<File> resource) {
        this.resources = resource;
    }

    @OptionArgument(shortName='R', argumentName="folder-name")
    @Description("Sets the special resource folder name whose files will " +
            "end up in the root of the resulting module CAR file (default: ROOT).")
    public void setResourceRoot(String resourceRootName) {
        this.resourceRootName = resourceRootName;
    }
   
    public String getOut() {
        return (out != null) ? out : DefaultToolOptions.getCompilerOutputRepo();
    }

    @Option
    @Description("Do **not** generate .src archive - useful when doing joint compilation")
    public void setSkipSrcArchive(boolean skip) {
        skipSrc = skip;
    }
    public boolean isSkipSrcArchive() {
        return skipSrc;
    }

    @Argument(argumentName="moduleOrFile", multiplicity="*")
    public void setModule(List<String> moduleOrFile) {
        this.files = moduleOrFile;
    }

    @Override
    public void initialize() throws IOException {
    }

    @Override
    public void run() throws Exception {
        setSystemProperties();
        AppendableWriter writer = new AppendableWriter(getOutAppendable());
        final Options opts = new Options()
                .cwd(cwd)
                .repos(getRepositoryAsStrings())
                .sourceDirs(roots)
                .resourceDirs(resources)
                .resourceRootName(resourceRootName)
                .systemRepo(systemRepo)
                .outRepo(getOut())
                .user(user)
                .pass(pass)
                .optimize(optimize)
                .modulify(modulify)
                .indent(indent)
                .comment(comments)
                .verbose(getVerbose())
                .profile(profile)
                .stdin(false)
                .generateSourceArchive(!skipSrc)
                .encoding(encoding)
                .diagnosticListener(diagnosticListener)
                .outWriter(writer);
        final TypeChecker typeChecker;
        if (opts.hasVerboseFlag("cmr")) {
            append("Using repositories: "+getRepositoryAsStrings());
            newline();
        }
        final RepositoryManager repoman = getRepositoryManager();
        long t0, t1, t2, t3, t4;
        final TypeCheckerBuilder tcb;
        List<File> onlySources = null;
        List<File> onlyResources = null;
        if (opts.isStdin()) {
            VirtualFile src = new VirtualFile() {
                @Override
                public boolean isFolder() {
                    return false;
                }
                @Override
                public String getName() {
                    return "SCRIPT.ceylon";
                }
                @Override
                public String getPath() {
                    return getName();
                }
                @Override
                public InputStream getInputStream() {
                    return System.in;
                }
                @Override
                public List<VirtualFile> getChildren() {
                    return Collections.emptyList();
                }
                @Override
                public int hashCode() {
                    return getPath().hashCode();
                }
                @Override
                public boolean equals(Object obj) {
                    if (obj instanceof VirtualFile) {
                        return ((VirtualFile) obj).getPath().equals(getPath());
                    }
                    else {
                        return super.equals(obj);
                    }
                }
            };
            t0 = System.nanoTime();
            tcb = new TypeCheckerBuilder()
                .addSrcDirectory(src);
        } else {
            t0=System.nanoTime();
            tcb = new TypeCheckerBuilder();
           
            SourceArgumentsResolver resolver = new SourceArgumentsResolver(roots, resources, Constants.CEYLON_SUFFIX, Constants.JS_SUFFIX);
            resolver
                .cwd(cwd)
                .expandAndParse(files);
            onlySources = resolver.getSourceFiles();
            onlyResources = resolver.getResourceFiles();
           
            if (opts.isVerbose()) {
                append("Adding source directories to typechecker:" + roots).newline();
            }
            for (File root : roots) {
                tcb.addSrcDirectory(root);
            }
            if (!resolver.getSourceModules().isEmpty()) {
                tcb.setModuleFilters(resolver.getSourceModules());
            }
            tcb.statistics(opts.isProfile());
            JsModuleManagerFactory.setVerbose(opts.isVerbose());
            tcb.moduleManagerFactory(new JsModuleManagerFactory(encoding));
        }
        //getting the type checker does process all types in the source directory
        tcb.verbose(opts.isVerbose()).setRepositoryManager(repoman);
        tcb.usageWarnings(false).encoding(encoding);

        typeChecker = tcb.getTypeChecker();
        if (onlySources != null) {
            for (PhasedUnit pu : typeChecker.getPhasedUnits().getPhasedUnits()) {
                File unitFile = new File(pu.getUnitFile().getPath());
                if (!FileUtil.containsFile(onlySources, unitFile)) {
                    if (opts.isVerbose()) {
                        append("Removing phased unit " + pu).newline();
                    }
                    typeChecker.getPhasedUnits().removePhasedUnitForRelativePath(pu.getPathRelativeToSrcDir());
                }
            }
        }
        t1=System.nanoTime();
        typeChecker.process(true);
       
        t2=System.nanoTime();
        JsCompiler jsc = new JsCompiler(typeChecker, opts);
        if (onlySources != null) {
            if (opts.isVerbose()) {
                append("Only these files will be compiled: " + onlySources).newline();
            }
            jsc.setSourceFiles(onlySources);
        }
        if (onlyResources != null) {
            jsc.setResourceFiles(onlyResources);
        }
        t3=System.nanoTime();
        if (!jsc.generate()) {
            if (jsc.getExitCode() != 0) {
                if(throwOnError)
                    throw new RuntimeException("Compiler exited with non-zero exit code: "+jsc.getExitCode());
                else {
                    jsc.printErrorsAndCount(writer);
                    System.exit(jsc.getExitCode());
                }
            }
            int count = jsc.printErrors(writer);
            throw new CompilerErrorException(String.format("%d errors.", count));
        }
        t4=System.nanoTime();
        if (opts.isProfile() || opts.hasVerboseFlag("benchmark")) {
            System.err.println("PROFILING INFORMATION");
            System.err.printf("TypeChecker creation:   %6d nanos%n", t1-t0);
            System.err.printf("TypeChecker processing: %6d nanos%n", t2-t1);
            System.err.printf("JS compiler creation:   %6d nanos%n", t3-t2);
            System.err.printf("JS compilation:         %6d nanos%n", t4-t3);
            System.out.println("Compilation finished.");
        }
    }

    /**
     * Sets the diagnostic listener. Not part of the command-line contract, only used by APIs.
     */
    public void setDiagnosticListener(DiagnosticListener diagnosticListener) {
        this.diagnosticListener = diagnosticListener;
    }
   
    /**
     * Tell the tool not to exit on a non-zero exit code from node, but throw otherwise. This is not
     * used by the command-line, but can be useful when invoked via the API.
     * @param throwOnError true to throw instead of calling System.exit. Defaults to false.
     */
    public void setThrowOnError(boolean throwOnError) {
        this.throwOnError = throwOnError;
    }
   
    /**
     * Check if we throw on a non-zero exit code from node, rather than exit. This is not
     * used by the command-line, but can be useful when invoked via the API.
     * @return true to throw instead of calling System.exit. Defaults to false.
     */
    public boolean isThrowOnError() {
        return throwOnError;
    }
}
TOP

Related Classes of com.redhat.ceylon.compiler.js.CeylonCompileJsTool$AppendableWriter

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.