Package com.redhat.ceylon.compiler.typechecker.context

Source Code of com.redhat.ceylon.compiler.typechecker.context.PhasedUnits

package com.redhat.ceylon.compiler.typechecker.context;

import java.util.ArrayList;
import java.util.List;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonToken;
import org.antlr.runtime.CommonTokenStream;

import com.redhat.ceylon.compiler.typechecker.analyzer.ModuleManager;
import com.redhat.ceylon.compiler.typechecker.io.VirtualFile;
import com.redhat.ceylon.compiler.typechecker.model.Module;
import com.redhat.ceylon.compiler.typechecker.model.Package;
import com.redhat.ceylon.compiler.typechecker.parser.CeylonLexer;
import com.redhat.ceylon.compiler.typechecker.parser.CeylonParser;
import com.redhat.ceylon.compiler.typechecker.parser.LexError;
import com.redhat.ceylon.compiler.typechecker.parser.ParseError;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.util.ModuleManagerFactory;

/**
* Contains phased units
*
* @author Emmanuel Bernard <emmanuel@hibernate.org>
*/
public class PhasedUnits extends PhasedUnitMap<PhasedUnit, PhasedUnit> {
    private final Context context;
    private final ModuleManager moduleManager;
    private List<String> moduleFilters;
    private String encoding;

    public PhasedUnits(Context context) {
        this.context = context;
        this.moduleManager = new ModuleManager(context);
        this.moduleManager.initCoreModules();
    }

    public PhasedUnits(Context context, ModuleManagerFactory moduleManagerFactory) {
        this.context = context;
        if(moduleManagerFactory != null){
            this.moduleManager = moduleManagerFactory.createModuleManager(context);
        }else{
            this.moduleManager = new ModuleManager(context);
        }
        this.moduleManager.initCoreModules();
    }
   
    public void setModuleFilters(List<String> moduleFilters){
        this.moduleFilters = moduleFilters;
    }
   
    public ModuleManager getModuleManager() {
        return moduleManager;
    }

    public void parseUnits(List<VirtualFile> srcDirectories) {
        for (VirtualFile file : srcDirectories) {
            parseUnit(file, file);
        }
    }

    public void parseUnit(VirtualFile srcDir) {
        parseUnit(srcDir, srcDir);
    }

    public void parseUnit(VirtualFile file, VirtualFile srcDir) {
        try {
            if (file.isFolder()) {
                //root directory is the src dir => start from here
                for (VirtualFile subfile : file.getChildren()) {
                    parseFileOrDirectory(subfile, srcDir);
                }
            }
            else {
                //simple file compilation
                //TODO is that really valid?
                parseFileOrDirectory(file, srcDir);
            }
        }
        catch (RuntimeException e) {
            //let it go
            throw e;
        }
        catch (Exception e) {
            throw new RuntimeException("Error while parsing the source directory: " + file.toString(), e);
        }
    }

    protected void parseFile(VirtualFile file, VirtualFile srcDir) throws Exception {
        if (file.getName().endsWith(".ceylon")) {

            //System.out.println("Parsing " + file.getName());
            CeylonLexer lexer = new CeylonLexer(new ANTLRInputStream(file.getInputStream(), getEncoding()));
            CommonTokenStream tokenStream = new CommonTokenStream(lexer);
            CeylonParser parser = new CeylonParser(tokenStream);
            Tree.CompilationUnit cu = parser.compilationUnit();
            List<CommonToken> tokens = new ArrayList<CommonToken>(tokenStream.getTokens().size());
            tokens.addAll(tokenStream.getTokens());
            PhasedUnit phasedUnit = new PhasedUnit(file, srcDir, cu,
                    moduleManager.getCurrentPackage(), moduleManager,
                    context, tokens);
            addPhasedUnit(file, phasedUnit);

            List<LexError> lexerErrors = lexer.getErrors();
            for (LexError le : lexerErrors) {
                //System.out.println("Lexer error in " + file.getName() + ": " + le.getMessage());
                cu.addLexError(le);
            }
            lexerErrors.clear();

            List<ParseError> parserErrors = parser.getErrors();
            for (ParseError pe : parserErrors) {
                //System.out.println("Parser error in " + file.getName() + ": " + pe.getMessage());
                cu.addParseError(pe);
            }
            parserErrors.clear();

        }
    }

    protected String getEncoding() {
    return encoding != null ? encoding : System.getProperty("file.encoding");
  }

    private void parseFileOrDirectory(VirtualFile file, VirtualFile srcDir) throws Exception {
        if (file.isFolder()) {
            processDirectory(file, srcDir);
        }
        else {
            parseFile(file, srcDir);
        }
    }

    private void processDirectory(VirtualFile dir, VirtualFile srcDir) throws Exception {
        moduleManager.push(dir.getName());
       
        // See if we're defining a new module
        final List<VirtualFile> files = dir.getChildren();
        boolean definesModule = false;
        for (VirtualFile file : files) {
            if (ModuleManager.MODULE_FILE.equals(file.getName())) {
                definesModule = true;
                break;
            }
        }

        if(checkModuleFilters(definesModule)){
            if(definesModule)
                moduleManager.visitModuleFile();
            for (VirtualFile file : files) {
                parseFileOrDirectory(file, srcDir);
            }
        }
        moduleManager.pop();
    }
   
    private boolean checkModuleFilters(boolean definesModule) {
        if(moduleFilters == null || moduleFilters.isEmpty())
            return true;
        Package pkg = moduleManager.getCurrentPackage();
        String pkgName = pkg.getNameAsString();
        /*
            ; filter example syntax:
            module-list+ (wanted-modules+) -> allowed-paths*
       
            ; Filter unwanted modules
            a, a.b, aa, b (a) -> a, a.b
       
            ; Filter unwanted longer-named modules
            a.b.c, a.b.d (a.b) ->
       
            ; Allow going to the module we're looking for
            a, a.b, a.b.c (a.b.c) -> a, a.b, a.b.c
       
            ; Allow any package in the default module
            a, b, c (default) -> a, b, c
        */
        for(String module : moduleFilters){
            // Are we looking for the default module?
            if(module.equals(Module.DEFAULT_MODULE_NAME)){
                // Allow anything for the default module if it's not owned by another module
                // and we're not defining a new module.
                if(pkg.getModule().isDefault() && !definesModule){
                    return true;
                }
                // None of the other rules apply to the default module.
                continue;
            }
            // Allow module folder.
            // We don't check for the presence of a module declaration here, we asked for this module so
            // if we're not defining it we will just have to deal with the error elsewhere (its absence).
            if(pkgName.equals(module)){
                return true;
            }
            // Allow sub-packages, but only if they are actually contained by the module itself
            // and not accidental modules with longer names.
            // We don't check for the presence of a module declaration here since that will generate
            // an error later because a module can't contain another module
            if(pkgName.startsWith(module + ".") && pkg.getModule().getNameAsString().equals(module)){
                return true;
            }
            // Allow the path that leads to the modules we're looking for, as long as they are in the default module
            // and we're not defining a new module
            if(module.startsWith(pkgName + ".") && pkg.getModule().isDefault() && !definesModule){
                return true;
            }
        }
        return false;
    }

    public void visitModules() {
        List<PhasedUnit> listOfUnits = getPhasedUnits();
        for (PhasedUnit pu : listOfUnits) {
            pu.visitSrcModulePhase();
        }
        for (PhasedUnit pu : listOfUnits) {
            pu.visitRemainingModulePhase();
        }
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    @Override
    protected PhasedUnit toStoredType(PhasedUnit phasedUnit) {
        return phasedUnit;
    }

    @Override
    protected PhasedUnit fromStoredType(PhasedUnit storedValue, String path) {
        return storedValue;
    }
}
TOP

Related Classes of com.redhat.ceylon.compiler.typechecker.context.PhasedUnits

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.