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.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 ClassOrInterfaceDeclaration) {
							result = innerScope.findSymbol(name, local, 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 - 2024 Weber Informatics LLC | Privacy Policy