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

org.walkmod.javalang.compiler.symbols.Scope 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.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import org.walkmod.javalang.ast.ImportDeclaration;
import org.walkmod.javalang.ast.Node;
import org.walkmod.javalang.ast.SymbolDefinition;
import org.walkmod.javalang.ast.body.ClassOrInterfaceDeclaration;
import org.walkmod.javalang.ast.expr.ObjectCreationExpr;
import org.walkmod.javalang.compiler.ArrayFilter;
import org.walkmod.javalang.compiler.Predicate;
import org.walkmod.javalang.compiler.PreviousPredicateAware;
import org.walkmod.javalang.compiler.reflection.CompatibleArgsPredicate;
import org.walkmod.javalang.compiler.reflection.ConstructorSorter;
import org.walkmod.javalang.compiler.reflection.ExecutableSorter;

public class Scope {

    private Map>> symbols = new HashMap>>();

    private List actions;

    private Symbol rootSymbol = null;

    private int innerAnonymousClassCounter = 0;

    private boolean hasMethodsLoaded = false;

    private boolean hasFieldsLoaded = false;

    private Map typeParams = null;

    private static ExecutableSorter sorter = new ExecutableSorter();

    private static ConstructorSorter constructorSorter = new ConstructorSorter();

    public Scope() {}

    public Scope(Symbol rootSymbol) {
        this.rootSymbol = rootSymbol;
    }

    public Scope(List actions) {
        this.actions = actions;

    }

    public void setRootSymbol(Symbol rootSymbol) {
        this.rootSymbol = rootSymbol;
    }

    public void setHasMethodsLoaded(boolean hasMethodsLoaded) {
        this.hasMethodsLoaded = hasMethodsLoaded;
    }

    public boolean hasFieldsLoaded() {
        return hasFieldsLoaded;
    }

    public void setHasFieldsLoaded(boolean hasFieldsLoaded) {
        this.hasFieldsLoaded = hasFieldsLoaded;
    }

    public Symbol getRootSymbol() {
        return rootSymbol;
    }

    public List> getSymbols() {
        List> result = new LinkedList>();

        Iterator>> it = symbols.values().iterator();
        while (it.hasNext()) {
            result.addAll(it.next());
        }
        return result;
    }

    public Symbol findSymbol(String name) {
        return findSymbol(name, false, null, ReferenceType.VARIABLE);
    }

    public Symbol findSymbol(String name, ReferenceType... referenceType) {
        return findSymbol(name, false, referenceType);
    }

    public Symbol findSymbol(String name, boolean local, ReferenceType... referenceType) {
        Symbol result = null;
        List> list = symbols.get(name);
        if (list != null) {
            Iterator> it = list.iterator();
            while (it.hasNext() && result == null) {
                Symbol s = it.next();
                if (referenceType == null || referenceType.length == 0) {
                    result = s;
                } else {
                    boolean found = false;
                    for (int i = 0; i < referenceType.length && !found; i++) {
                        found = s.getReferenceType().equals(referenceType[i]);
                    }
                    if (found) {
                        result = s;
                    }
                }
            }
        }
        if (result == null) {
            list = symbols.get("super");
            if (list != null) {
                Symbol superSymbol = list.get(0);
                Scope scope = superSymbol.getInnerScope();
                if (scope != null) {
                    if (!local || superSymbol.getLocation() instanceof ClassOrInterfaceDeclaration) {
                        result = scope.findSymbol(name, local, referenceType);
                    }

                }
            }

        }
        return result;
    }

    public List> getSymbols(String name) {
        return symbols.get(name);
    }

    public List> getSymbolsByLocation(Node node) {
        List> result = new LinkedList>();
        Collection>> values = symbols.values();
        Iterator>> it = values.iterator();
        while (it.hasNext()) {
            List> list = it.next();
            for (Symbol symbol : list) {
                if (symbol.getLocation() == node) {// yes, by reference
                    result.add(symbol);
                }
            }
        }

        return result;
    }

    public List> getSymbolsByType(String typeName, ReferenceType referenceType) {
        List> result = new LinkedList>();
        Collection>> values = symbols.values();
        Iterator>> it = values.iterator();
        while (it.hasNext()) {
            List> list = it.next();
            for (Symbol symbol : list) {
                if (symbol.getReferenceType() == referenceType) {// yes, by
                                                                 // reference

                    if (symbol.getType().getName().startsWith(typeName)) {
                        result.add(symbol);
                    }
                }
            }
        }

        return result;

    }

    public List> getSymbolsByType(ReferenceType... referenceType) {
        List> result = new LinkedList>();
        Collection>> values = symbols.values();
        Iterator>> it = values.iterator();
        while (it.hasNext()) {
            List> list = it.next();
            for (Symbol symbol : list) {
                boolean found = false;

                if (referenceType == null || referenceType.length == 0) {

                    found = true;
                } else {

                    for (int i = 0; i < referenceType.length && !found; i++) {
                        found = symbol.getReferenceType() == referenceType[i];
                    }
                }
                if (found) {
                    result.add(symbol);
                }
            }
        }

        return result;

    }

    public Map getTypeParams() {
        Map aux = new HashMap();
        List> superSymbol = symbols.get("super");
        if (superSymbol != null) {
            Scope superScope = superSymbol.get(0).getInnerScope();
            if (superScope != null) {

                aux.putAll(superScope.getTypeParams());
            }
        }
        if (typeParams != null) {
            aux.putAll(typeParams);
        }

        return aux;
    }

    public Map getLocalTypeParams() {
        return typeParams;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private Method runPredicatesOnMethodCalls(List> predicates, Map execs,
            SymbolType[] args) {
        Method[] methods = new Method[execs.size()];

        List sortedMethods = sorter.sort(execs.values().toArray(methods), SymbolType.toClassArray(args));
        ArrayFilter filter = new ArrayFilter(sortedMethods.toArray(methods));
        CompatibleArgsPredicate cap = new CompatibleArgsPredicate(args);
        cap.setTypeMapping(getTypeParams());
        filter.appendPredicate(cap);
        if (predicates != null && !predicates.isEmpty()) {
            Predicate first = predicates.get(0);
            if (first instanceof PreviousPredicateAware) {
                ((PreviousPredicateAware) first).setPreviousPredicate(cap);
            }
            for (Predicate pred : predicates) {
                filter.appendPredicate(pred);
            }
        }

        Method exec = null;

        try {
            exec = filter.filterOne();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return exec;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    private Constructor runPredicatesOnConstructors(List> predicates, Map execs,
            SymbolType[] args) {
        Constructor[] methods = new Constructor[execs.size()];
        List sortedMethods =
                constructorSorter.sort(execs.values().toArray(methods), SymbolType.toClassArray(args));
        ArrayFilter filter = new ArrayFilter(sortedMethods.toArray(methods));
        CompatibleArgsPredicate cap = new CompatibleArgsPredicate(args);
        cap.setTypeMapping(getTypeParams());
        filter.appendPredicate(cap);
        if (predicates != null && !predicates.isEmpty()) {
            Predicate first = predicates.get(0);
            if (first instanceof PreviousPredicateAware) {
                ((PreviousPredicateAware) first).setPreviousPredicate(cap);
            }
            for (Predicate pred : predicates) {
                filter.appendPredicate(pred);
            }
        }

        Constructor exec = null;

        try {
            exec = filter.filterOne();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return exec;
    }

    public Symbol findSymbol(String name, SymbolType scope, SymbolType[] args, List> predicates,
            ReferenceType... referenceType) {
        return findSymbol(name, false, scope, args, predicates, referenceType);
    }

    public Symbol findSymbol(String name, boolean local, SymbolType scope, SymbolType[] args,
            List> predicates, ReferenceType... referenceType) {

        Symbol result = null;
        if (args == null) {

            return findSymbol(name, local, referenceType);

        } else {

            List> values = symbols.get(name);
            if (values != null) {
                Iterator> it = values.iterator();

                Map execs = new HashMap();

                int i = 0;
                boolean isConstructor = false;
                while (it.hasNext()) {
                    Symbol symbol = it.next();
                    if (symbol instanceof MethodSymbol) {
                        MethodSymbol aux = (MethodSymbol) symbol;
                        Object m = aux.getReferencedMethod();
                        if (m == null) {
                            m = aux.getReferencedConstructor();
                            isConstructor = true;
                        }

                        if (m != null) {
                            if (local && rootSymbol != null) {
                                Node location = aux.getLocation();
                                if (location != null && location.getParentNode() == rootSymbol.getLocation()) {
                                    execs.put(i, m);
                                }
                            } else {
                                execs.put(i, m);
                            }
                        }

                    }
                    i++;
                }
                if (execs.isEmpty()) {
                    result = null;
                } else {
                    Object exec = null;
                    if (isConstructor) {
                        exec = runPredicatesOnConstructors(predicates, execs, args);
                    } else {
                        exec = runPredicatesOnMethodCalls(predicates, execs, args);
                    }
                    Set keys = execs.keySet();
                    Iterator itKeys = keys.iterator();
                    while (itKeys.hasNext() && result == null) {
                        Integer key = itKeys.next();
                        if (execs.get(key) == exec) {
                            result = values.get(key);
                        }
                    }
                }
            }
            if (result == null) {
                values = symbols.get("super");
                if (values != null) {
                    Symbol superSymbol = values.get(0);

                    Scope innerScope = superSymbol.getInnerScope();
                    if (innerScope != null) {
                        if (!local || superSymbol.getLocation() instanceof ObjectCreationExpr
                                || superSymbol.getLocation() instanceof ClassOrInterfaceDeclaration) {
                            result = innerScope.findSymbol(name, false, scope, args, predicates, referenceType);
                        }

                    }
                }
            }
            if (result != null) {
                MethodSymbol sm = (MethodSymbol) result;
                result = sm.buildTypeParameters(typeParams);
            }

        }
        return result;
    }

    public void chageSymbol(Symbol oldSymbol, Symbol newSymbol) {
        List> list = symbols.get(oldSymbol.getName());
        if (list.remove(oldSymbol)) {
            ArrayList> values = symbols.get(newSymbol.getName());
            if (values == null) {
                values = new ArrayList>();
                symbols.put(newSymbol.getName(), values);
            }
            values.add(newSymbol);
        }
    }

    public  Symbol addSymbol(String symbolName, SymbolType type, T location) {

        return addSymbol(symbolName, type, ReferenceType.VARIABLE, location);
    }

    public  Symbol addSymbol(String symbolName, SymbolType type,
            ReferenceType referenceType, T location) {

        Symbol s = new Symbol(symbolName, type, location, referenceType);
        if (addSymbol(s)) {
            return s;
        }
        return null;
    }

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

    public  boolean addSymbol(Symbol symbol, boolean override) {
        String name = symbol.getName();
        ArrayList> values = symbols.get(name);
        boolean added = false;
        if (values == null) {
            values = new ArrayList>();
            symbols.put(symbol.getName(), values);
        } else {
            if (override) {
                Iterator> it = values.iterator();
                while (it.hasNext()) {
                    Symbol value = it.next();

                    if (!value.getReferenceType().equals(ReferenceType.METHOD)
                            && value.getReferenceType().equals(symbol.getReferenceType())) {
                        Object originalLocation = value.getLocation();
                        Object newLocation = symbol.getLocation();

                        if (originalLocation != null && newLocation != null
                                && (originalLocation instanceof ImportDeclaration)
                                && (newLocation instanceof ImportDeclaration)) {
                            // there is an import override, the non asterisk has
                            // priority
                            ImportDeclaration newImport = (ImportDeclaration) newLocation;
                            ImportDeclaration originalImport = (ImportDeclaration) originalLocation;

                            if (originalImport.isAsterisk() && !newImport.isAsterisk()) {
                                it.remove();
                            } else if (!originalImport.isAsterisk() && newImport.isAsterisk()) {
                                added = true;
                            }

                        } else {
                            it.remove();
                        }
                    }
                }
            }
        }
        if (symbol.getReferenceType().equals(ReferenceType.TYPE_PARAM)) {
            if (typeParams == null) {
                typeParams = new LinkedHashMap();
            }

            if (!typeParams.containsKey(name)) {
                typeParams.put(name, symbol.getType());
            } else {
                added = true;
            }
        }
        if (values.isEmpty()) {
            values.add(symbol);
        } else {
            int pos = values.size();

            if (symbol.getReferenceType().equals(ReferenceType.METHOD)) {
                MethodSymbol ms = (MethodSymbol) symbol;
                Method refMethod = ms.getReferencedMethod();

                if (refMethod != null) {
                    ListIterator> it = values.listIterator(values.size());

                    ExecutableSorter cmp = new ExecutableSorter();
                    while (it.hasPrevious() && !added) {
                        Symbol aux = it.previous();
                        if (aux instanceof MethodSymbol) {
                            MethodSymbol auxMethod = (MethodSymbol) aux;
                            Method md = auxMethod.getReferencedMethod();
                            if (md != null) {
                                if (cmp.compare(refMethod, md) == 1) {
                                    values.add(pos, ms);
                                    added = true;
                                }
                            }
                        }
                        pos--;
                    }
                    if (!added) {
                        pos = 0;
                    }
                }
            }
            if (!added) {
                values.add(pos, symbol);
            }
        }
        return true;
    }

    public boolean hasMethodsLoaded() {
        return hasMethodsLoaded;
    }

    public List getActions() {
        return actions;
    }

    public void addActions(List actions) {
        if (this.actions == null) {
            this.actions = actions;
        } else {
            this.actions.addAll(actions);
        }
    }

    public int getInnerAnonymousClassCounter() {
        return innerAnonymousClassCounter;
    }

    public void incrInnerAnonymousClassCounter() {
        innerAnonymousClassCounter++;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy