Package com.redhat.ceylon.compiler.js

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

package com.redhat.ceylon.compiler.js;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;

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.VFS;
import com.redhat.ceylon.compiler.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.compiler.typechecker.model.Value;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ClassDefinition;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.InterfaceDefinition;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDefinition;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.ObjectDefinition;

/** This visitor finds all the shared class and interface definitions in the language module,
* along with all their shared actual methods, and checks that they are also defined in the
* JS version of the language module.
*
* @author Enrique Zamudio
*/
public class ModuleComplianceVisitor extends Visitor {

    /** The complete JS language module as a String */
    private String js;
    /** The last class or interface definition that was visited. */
    private ClassOrInterface last;
    /** The last object definition visited. */
    private Value lastObject;

    public ModuleComplianceVisitor(String jsLanguageModule) {
        js = jsLanguageModule;
    }

    @Override
    public void visit(ClassDefinition that) {
        if (!(that.getDeclarationModel().isShared() && that.getDeclarationModel().isToplevel()) || that.getDeclarationModel().isAlias()) {
            return;
        }
        last = that.getDeclarationModel();
        String def = String.format("exports.%s=", last.getName());
        if (js.indexOf(def) < 0) {
            System.out.println("Missing CLASS:     " + last.getName());
        }
        super.visit(that);
        last = null;
    }
    @Override
    public void visit(InterfaceDefinition that) {
        if (!(that.getDeclarationModel().isShared() && that.getDeclarationModel().isToplevel()) || that.getDeclarationModel().isAlias()) {
            return;
        }
        last = that.getDeclarationModel();
        String def = String.format("exports.%s=", last.getName());
        if (js.indexOf(def) < 0) {
            System.out.println("Missing INTERFACE: " + last.getName());
        }
        super.visit(that);
        last = null;
    }
    @Override
    public void visit(MethodDefinition that) {
        if (!that.getDeclarationModel().isShared() || that.getDeclarationModel().isFormal()) {
            return;
        }
        String def;
        String id = that.getIdentifier().getText().trim();
        if (that.getDeclarationModel().isToplevel()) {
            def = String.format("exports.%s=", id);
        } else if (that.getScope().getContainer() == last || that.getScope().getContainer() == lastObject) {
            def = String.format("%s$proto.%s = function(", last.getName(), id);
            if (js.indexOf(def) < 0) {
                def = String.format("%s.$$.prototype.%s = function", last.getName(), id);
            }
            if (js.indexOf(def) < 0) {
                System.out.println("Missing METHOD:    "
                    + (last == null || that.getDeclarationModel().isToplevel() ? "" : last.getName()+".")
                    + id);
            }
        }
        super.visit(that);
    }

    @Override
    public void visit(ObjectDefinition that) {
        if (!(that.getDeclarationModel().isShared() && that.getDeclarationModel().isToplevel())) {
            return;
        }
        lastObject = that.getDeclarationModel();
        //The object names in JS are like a getter
        String def = String.format("exports.get%s%s=", lastObject.getName().substring(0,1).toUpperCase(),
                lastObject.getName().substring(1));
        if (js.indexOf(def) < 0) {
            System.out.println("Missing OBJECT:    " + lastObject.getName());
        }
        super.visit(that);
        lastObject = null;
    }

    /** This is a convenience method to find either the JS language module or the .src file for the
     * Ceylon Language Module.
     * @param root The root directory to look for the file.
     * @param extension The file extension (.js or .src) */
    public static File findModule(String root, String extension) {
        File r = new File(root);
        if (r.exists() && r.isDirectory()) {
            r = new File(r, "ceylon");
            if (r.exists() && r.isDirectory()) {
                r = new File(r, "language");
            }
            if (r.exists() && r.isDirectory()) {
                //Get the lastest version
                File which = null;
                for (File s : r.listFiles()) {
                    if (which == null || s.lastModified() > which.lastModified()) {
                        which = s;
                    }
                }
                if (which != null) {
                    for (File s : which.listFiles()) {
                        if (s.getName().equals("ceylon.language-" + which.getName() + "." + extension)) {
                            return s;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static void main(String[] args) throws IOException {
        System.out.println("Finding JS language module...");
        File jsmod = findModule("build/runtime", "js");
        if (jsmod == null && System.getenv("ceylon.repo") != null) {
            jsmod = findModule(System.getenv("ceylon.repo"), "js");
        }
        if (jsmod == null && System.getProperty("user.home") != null) {
            jsmod = findModule(System.getProperty("user.home"), "js");
        }
        if (jsmod == null) {
            throw new IllegalStateException("Cannot find JS language module");
        }
        System.out.println("Finding Ceylon Language Module");
        File mod = findModule("../ceylon.language/build/dist", "src");
        if (mod == null && System.getenv("ceylon.repo") != null) {
            mod = findModule(System.getenv("ceylon.repo"), "src");
        }
        if (mod == null && System.getProperty("user.home") != null) {
            mod = findModule(System.getProperty("user.home"), "src");
        }
        if (mod == null) {
            throw new IllegalStateException("Cannot find JVM language module");
        }
        System.out.println("Reading JS language module into memory...");
        FileReader reader = new FileReader(jsmod);
        char[] buf = new char[16384];
        StringWriter writer = new StringWriter();
        while (reader.ready()) {
            reader.read(buf);
            writer.write(buf);
        }
        reader.close();
        ModuleComplianceVisitor v = new ModuleComplianceVisitor(writer.toString());
        System.out.println("Checking Ceylon vs JS modules...");
        VFS vfs = new VFS();
        TypeChecker tc = new TypeCheckerBuilder().verbose(false)
                .addSrcDirectory(vfs.getFromZipFile(mod)).getTypeChecker();
        tc.process();
        for (PhasedUnit pu : tc.getPhasedUnits().getPhasedUnits()) {
            pu.getCompilationUnit().visit(v);
        }
    }
}
TOP

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

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.