All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.walkmod.javalang.compiler.symbols.SymbolTable Maven / Gradle / Ivy

There is a newer version: 2.3.10
Show newest version
/*
 * Copyright (C) 2015 Raquel Pau and Albert Coroleu.
 * 
 * Walkmod is free software: you can redistribute it and/or modify it under the terms of the GNU
 * Lesser General Public License as published by the Free Software Foundation, either version 3 of
 * the License, or (at your option) any later version.
 * 
 * Walkmod is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with Walkmod. If
 * not, see .
 */
package org.walkmod.javalang.compiler.symbols;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import org.walkmod.javalang.ast.Node;
import org.walkmod.javalang.ast.SymbolDataAware;
import org.walkmod.javalang.ast.SymbolDefinition;
import org.walkmod.javalang.ast.SymbolReference;
import org.walkmod.javalang.ast.body.ClassOrInterfaceDeclaration;
import org.walkmod.javalang.ast.body.EnumConstantDeclaration;
import org.walkmod.javalang.ast.body.TypeDeclaration;
import org.walkmod.javalang.ast.expr.ObjectCreationExpr;
import org.walkmod.javalang.ast.stmt.TypeDeclarationStmt;
import org.walkmod.javalang.compiler.Predicate;
import org.walkmod.javalang.exceptions.SymbolTableException;

public class SymbolTable {

    private Stack indexStructure;

    private SymbolFactory symbolFactory = null;

    private List actions;

    public SymbolTable() {
        indexStructure = new Stack();
        setSymbolFactory(new DefaultSymbolFactory());
    }

    public void setActions(List actions) {
        this.actions = actions;
    }

    public Stack getScopes() {
        return indexStructure;
    }

    public void setSymbolFactory(SymbolFactory symbolFactory) {
        this.symbolFactory = symbolFactory;
    }

    public SymbolType getType(String symbolName, ReferenceType... referenceType) {
        Symbol s = findSymbol(symbolName, referenceType);
        if (s != null) {
            return s.getType();
        }
        return null;
    }

    public Symbol findSymbol(String symbolName, ReferenceType... referenceType) {
        return findSymbol(symbolName, null, null, referenceType);
    }

    public Symbol findSymbol(String symbolName, SymbolType symbolScope, SymbolType[] args,
            ReferenceType... referenceType) {
        return findSymbol(symbolName, symbolScope, args, null, referenceType);
    }

    public Symbol findSymbol(String symbolName, SymbolType symbolScope, SymbolType[] args,
            List> predicates, ReferenceType... referenceType) {
        int j = indexStructure.size() - 1;
        Symbol result = null;
        if (symbolScope != null) {
            Class clazz = symbolScope.getClazz();
            Symbol scopeSymbol = null;
            if (clazz.isAnonymousClass()) {
                scopeSymbol = findSymbol(symbolScope.getClazz().getName(), ReferenceType.TYPE);
            } else {
                scopeSymbol =
                        indexStructure.get(0).findSymbol(symbolScope.getClazz().getCanonicalName(), ReferenceType.TYPE);
            }
            if (scopeSymbol != null) {
                if (scopeSymbol.getInnerScope() != null) {
                    // it is an inner class
                    return scopeSymbol.getInnerScope().findSymbol(symbolName, symbolScope, args, predicates,
                            referenceType);
                } else
                    return null;
            }

        }

        Scope currentTypeScope = null;
        SymbolType auxScope = null;

        while (j >= 0 && result == null) {
            Scope scope = indexStructure.get(j);
            Symbol rootSymbol = scope.getRootSymbol();

            if (symbolScope == null && rootSymbol != null) {
                SymbolDefinition sd = rootSymbol.getLocation();
                if (sd instanceof SymbolDataAware) {
                    auxScope = (SymbolType) ((SymbolDataAware) sd).getSymbolData();
                    if (currentTypeScope == null && !(rootSymbol instanceof MethodSymbol)) {
                        currentTypeScope = scope;
                    }
                }

            }
            if (auxScope == null) {
                auxScope = symbolScope;
            }

            SymbolType typeRootSymbol = null;
            if (rootSymbol != null && !(rootSymbol instanceof MethodSymbol)) {
                typeRootSymbol = rootSymbol.getType();
            }
            if (typeRootSymbol != null && symbolScope != null) {

                if (typeRootSymbol.isCompatible(symbolScope)) {
                    result = scope.findSymbol(symbolName, true, auxScope, args, predicates, referenceType);
                }
            } else {
                result = scope.findSymbol(symbolName, true, auxScope, args, predicates, referenceType);
            }

            j--;
        }

        if (currentTypeScope != null && result == null) {
            if (symbolScope == null || auxScope.getName().equals(symbolScope.getName())) {
                result = currentTypeScope.findSymbol(symbolName, false, symbolScope, args, predicates, referenceType);
            }
        }

        return result;
    }

    public List> findSymbolsByType(String typeName, ReferenceType referenceType) {
        List> result = new LinkedList>();
        int i = indexStructure.size() - 1;
        while (i >= 0) {
            Scope scope = indexStructure.get(i);
            result.addAll(scope.getSymbolsByType(typeName, referenceType));
            i--;
        }
        return result;
    }

    public ArrayList> findSymbolsByType(ReferenceType... referenceType) {
        ArrayList> result = new ArrayList>();
        int i = indexStructure.size() - 1;
        while (i >= 0) {
            Scope scope = indexStructure.get(i);
            result.addAll(scope.getSymbolsByType(referenceType));
            i--;
        }
        return result;
    }

    public List> findSymbolsByLocation(Node node) {
        List> result = new LinkedList>();
        int i = indexStructure.size() - 1;
        while (i >= 0) {
            Scope scope = indexStructure.get(i);
            result.addAll(scope.getSymbolsByLocation(node));
            i--;
        }
        return result;
    }

    private void invokeActions(Scope scope, Symbol s, SymbolEvent event, SymbolReference reference)
            throws Exception {
        if (s != null) {
            if (actions != null) {
                for (SymbolAction action : actions) {
                    action.execute(s, this, event, reference);
                }
            }

            if (scope != null) {
                List scopeActions = scope.getActions();
                if (scopeActions != null) {
                    for (SymbolAction action : scopeActions) {
                        action.execute(s, this, event, reference);
                    }
                }
            }
            s.invokeActions(this, event, reference);
        }
    }

    public Symbol lookUpSymbolForRead(String symbolName, SymbolReference reference, ReferenceType... referenceType) {
        return lookUpSymbolForRead(symbolName, reference, null, null, referenceType);
    }

    public Symbol lookUpSymbolForRead(String symbolName, SymbolReference reference, SymbolType symbolScope,
            SymbolType[] args, ReferenceType... referenceType) {
        Symbol s = findSymbol(symbolName, symbolScope, args, referenceType);
        if (s != null) {
            try {
                invokeActions(indexStructure.peek(), s, SymbolEvent.READ, reference);
            } catch (Exception e) {
                throw new SymbolTableException(e);
            }
        }
        return s;
    }

    public Symbol lookUpSymbolForWrite(String symbolName, SymbolReference reference) {
        return lookUpSymbolForWrite(symbolName, reference, null, null);
    }

    public Map getTypeParams() {
        Map result = new LinkedHashMap();

        Iterator it = indexStructure.iterator();
        while (it.hasNext()) {
            Scope scope = it.next();
            Map tp = scope.getLocalTypeParams();
            if (tp != null) {
                result.putAll(tp);
            }
        }
        return result;
    }

    public Map flat() {
        Map result = new LinkedHashMap();

        Iterator it = indexStructure.iterator();
        while (it.hasNext()) {
            Scope scope = it.next();
            List> symbols = scope.getSymbols();
            for (Symbol s : symbols) {
                result.put(s.getName(), s.getType());
            }
        }
        return result;
    }

    public Symbol lookUpSymbolForWrite(String symbolName, SymbolReference reference, SymbolType symbolScope,
            SymbolType[] args, ReferenceType... referenceType) {

        if (referenceType == null || referenceType.length == 0) {
            referenceType = new ReferenceType[1];
            referenceType[0] = ReferenceType.VARIABLE;
        }
        Symbol s = findSymbol(symbolName, symbolScope, args, referenceType);
        try {
            invokeActions(indexStructure.peek(), s, SymbolEvent.WRITE, reference);
        } catch (Exception e) {
            throw new SymbolTableException(e);
        }
        return s;
    }

    public boolean containsSymbol(String symbolName, ReferenceType referenceType) {
        SymbolType type = getType(symbolName, referenceType);
        return (type != null);
    }

    public int getScopeLevel() {
        if (indexStructure != null) {
            return indexStructure.size() - 1;
        }
        return 0;
    }

    public boolean pushSymbol(Symbol symbol) {
        return pushSymbol(symbol, false);
    }

    public String generateAnonymousClass() {
        return getTypeAnonymousClassPreffix(null);

    }

    private String getTypeAnonymousClassPreffix(String name) {
        int j = indexStructure.size() - 2;
        String suffixName = null;

        // we upgrade the class counter in the closest inner class
        while (j > 0 && suffixName == null) {
            Scope sc = indexStructure.get(j);
            Symbol rootSymbol = sc.getRootSymbol();
            if (rootSymbol != null) {
                SymbolDefinition sd = rootSymbol.getLocation();
                if (sd instanceof ObjectCreationExpr || sd instanceof TypeDeclaration
                        || sd instanceof TypeDeclarationStmt || sd instanceof EnumConstantDeclaration) {

                    int num = 1;
                    String preffix = ((SymbolDataAware) sd).getSymbolData().getName();
                    if (name == null) {
                        sc.incrInnerAnonymousClassCounter();
                        num = sc.getInnerAnonymousClassCounter();
                    } else {
                        num = 1;

                        Symbol aux =
                                indexStructure.get(0).findSymbol(preffix + "$" + num + name, ReferenceType.TYPE);

                        while (aux != null) {
                            num++;
                            aux = indexStructure.get(0).findSymbol(preffix + "$" + num + name, ReferenceType.TYPE);

                        }

                    }

                    suffixName = "$" + num;
                    return preffix + suffixName;
                }

            }
            j--;
        }
        return null;
    }

    public String getTypeStatementPreffix(String name) {
        return getTypeAnonymousClassPreffix(name);
    }

    public boolean pushSymbol(Symbol symbol, boolean override) {
        Scope lastScope = indexStructure.peek();

        if (lastScope.addSymbol(symbol, override)) {
            try {
                invokeActions(lastScope, symbol, SymbolEvent.PUSH, null);
            } catch (Exception e) {
                throw new SymbolTableException(e);
            }
            return true;
        } else {
            return false;
        }

    }

    public Symbol pushSymbol(String symbolName, ReferenceType referenceType, SymbolType symbolType, Node location) {
        return pushSymbol(symbolName, referenceType, symbolType, location, false);
    }

    public Symbol pushSymbol(String symbolName, ReferenceType referenceType, SymbolType symbolType, Node location,
            boolean override) {
        Symbol symbol = symbolFactory.create(symbolName, referenceType, symbolType, location);
        if (pushSymbol(symbol, override)) {
            return symbol;
        }
        return null;
    }

    public Symbol pushSymbol(String symbolName, ReferenceType referenceType, SymbolType symbolType, Node location,
            SymbolAction action) {
        Symbol symbol = symbolFactory.create(symbolName, referenceType, symbolType, location, action);
        if (pushSymbol(symbol, false)) {
            return symbol;
        }
        return null;
    }

    public Symbol pushSymbol(String symbolName, ReferenceType referenceType, SymbolType symbolType, Node location,
            List actions) {
        return pushSymbol(symbolName, referenceType, symbolType, location, actions, false);
    }

    public Symbol pushSymbol(String symbolName, ReferenceType referenceType, SymbolType symbolType, Node location,
            List actions, boolean override) {
        Symbol symbol = symbolFactory.create(symbolName, referenceType, symbolType, location, actions);
        if (pushSymbol(symbol, override)) {
            return symbol;
        }
        return null;
    }

    public List> pushSymbols(Set names, ReferenceType referenceType, SymbolType symbolType,
            Node location, List actions) {
        List> pushedSymbols = new LinkedList>();

        for (String name : names) {
            Symbol s = pushSymbol(name, referenceType, symbolType, location, actions);
            if (s != null) {
                pushedSymbols.add(s);
            }
        }
        return pushedSymbols;
    }

    public Scope popScope() {
        return popScope(false);
    }

    public Scope popScope(boolean silent) {
        Scope scope = indexStructure.peek();
        if (!silent) {
            List> symbols = scope.getSymbols();
            for (Symbol symbol : symbols) {
                try {
                    invokeActions(scope, symbol, SymbolEvent.POP, null);
                } catch (Exception e) {
                    throw new SymbolTableException(e);
                }
            }
        }
        return indexStructure.pop();
    }

    public void pushScope() {
        pushScope(null, null);
    }

    public void pushScope(Scope scope) {
        pushScope(scope, null);
    }

    public void addActionsToScope(List actions) {
        indexStructure.peek().addActions(actions);
    }

    public void pushScope(Scope scope, List actions) {
        if (scope == null) {
            scope = new Scope(actions);
        }
        indexStructure.push(scope);

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy