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