summaryrefslogblamecommitdiff
path: root/sources/scalac/checkers/CheckOwners.java
blob: 2bc09016f8d949a66004fd7a5399d721ac6854aa (plain) (tree)























































                                                                          
                                                      











                                               

                                        





























                                                                   
                                           



                                         

                                                                  






                                                                       
                                                        



                              
                                         















                                                               
                                                                       
                        
                                         






                                                                                 







                                  
                                   



                                                    
                                                               
             


         
/*     ____ ____  ____ ____  ______                                     *\
**    / __// __ \/ __// __ \/ ____/    SOcos COmpiles Scala             **
**  __\_ \/ /_/ / /__/ /_/ /\_ \       (c) 2002, LAMP/EPFL              **
** /_____/\____/\___/\____/____/                                        **
\*                                                                      */

// $Id$

package scalac.checkers;

import scalac.util.*;
import scalac.ast.*;
import scalac.symtab.*;
import scalac.Global;
import scalac.util.Debug;
import Tree.*;

/**
 * Check that the owner of symbols is set correctly.
 *
 * @author Michel Schinz
 * @version 1.0
 */

public class CheckOwners extends Checker {
    protected Symbol currentOwner;

    public CheckOwners(Global global) {
        super(global);
	currentOwner = global.definitions.ROOT_CLASS;
    }

    protected void traverse(Tree tree, Symbol owner) {
        Symbol prevOwner = currentOwner;
        currentOwner = owner;
        traverse(tree);
        currentOwner = prevOwner;
    }

    protected void traverse(Tree[] array, Symbol owner) {
        Symbol prevOwner = currentOwner;
        currentOwner = owner;
        traverse(array);
        currentOwner = prevOwner;
    }

    protected void traverse(Tree[][] array, Symbol owner) {
        Symbol prevOwner = currentOwner;
        currentOwner = owner;
        traverse(array);
        currentOwner = prevOwner;
    }

    protected void traverse(Template templ, Symbol owner) {
	Symbol prevOwner = currentOwner;
	if (owner.kind == Kinds.CLASS)
	    currentOwner = owner.primaryConstructor();
	traverse(templ.parents);
	currentOwner = owner;

        Symbol templSymbol = templ.symbol();
        Tree[] body = templ.body;
        for (int i = 0; i < body.length; ++i) {
            switch (body[i]) {
            case PackageDef(_,_):
            case ClassDef(_,_,_,_,_,_):
            case ModuleDef(_,_,_,_):
            case DefDef(_,_,_,_,_,_):
            case ValDef(_,_,_,_):
            case AbsTypeDef(_,_,_, _):
            case AliasTypeDef(_,_,_, _):
                traverse(body[i], owner);
                break;
            default:
                traverse(body[i], templSymbol);
            }
        }

	currentOwner = prevOwner;
    }

    protected void checkOwner(Tree tree, Symbol sym) {
        Symbol owner = sym.owner();
        verify(tree,
               owner == currentOwner,
               "owner",
               "incorrect owner for " + Debug.toString(sym) + ":\n"
               + "  found:    " + Debug.toString(owner) + "\n"
               + "  required: " + Debug.toString(currentOwner));
    }

    public void traverse(Tree tree) {
	switch(tree) {
	case PackageDef(Tree packaged, Template impl):
            check(tree);
            traverse(packaged);
            traverse(impl, packaged.symbol());
            break;

        case ClassDef(int mods,
                      Name name,
                      AbsTypeDef[] tparams,
                      ValDef[][] vparams,
		      Tree tpe,
                      Template impl): {
            check(tree);
            traverse(tparams, tree.symbol().primaryConstructor());
            traverse(vparams, tree.symbol().primaryConstructor());
	    traverse(tpe);
            traverse(impl, tree.symbol());
        } break;

        case ModuleDef(int mods, Name name, Tree tpe, Template impl): {
            check(tree);
            traverse(tpe);
            traverse(impl, tree.symbol().moduleClass());
        } break;

        case DefDef(int mods,
                    Name name,
                    AbsTypeDef[] tparams,
                    ValDef[][] vparams,
                    Tree tpe,
                    Tree rhs): {
            check(tree);
            traverse(tparams, tree.symbol());
            traverse(vparams, tree.symbol());
            traverse(tpe, tree.symbol());
            traverse(rhs, tree.symbol());
        } break;

        case ValDef(int mods, Name name, Tree tpe, Tree rhs): {
            check(tree);
            traverse(tpe);
            traverse(rhs, tree.symbol());
        } break;

        case AbsTypeDef(int mods, Name name, Tree rhs, Tree lobound): {
            check(tree);
            traverse(rhs, tree.symbol());
	    traverse(lobound, tree.symbol());
        } break;

        case AliasTypeDef(int mods, Name name, AbsTypeDef[] tparams, Tree rhs): {
            check(tree);
            traverse(tparams, tree.symbol());
            traverse(rhs, tree.symbol());
        } break;

	default:
	    super.traverse(tree);
        }
    }

    public void check(Tree tree) {
        if (tree.definesSymbol()) {
            Symbol sym = tree.symbol();
            if (sym != null && sym != Symbol.NONE) {
                checkOwner(tree, sym);
                if (sym.kind == Kinds.CLASS)
                    checkOwner(tree, sym.primaryConstructor());
            }
        }
    }
}