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

org.walkmod.javalang.compiler.actions.RemoveUnusedSymbolsAction 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.actions;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.walkmod.javalang.ast.ImportDeclaration;
import org.walkmod.javalang.ast.Node;
import org.walkmod.javalang.ast.body.FieldDeclaration;
import org.walkmod.javalang.ast.body.MethodDeclaration;
import org.walkmod.javalang.ast.body.ModifierSet;
import org.walkmod.javalang.ast.body.TypeDeclaration;
import org.walkmod.javalang.ast.body.VariableDeclarator;
import org.walkmod.javalang.ast.expr.Expression;
import org.walkmod.javalang.ast.expr.LiteralExpr;
import org.walkmod.javalang.ast.expr.NameExpr;
import org.walkmod.javalang.ast.expr.VariableDeclarationExpr;
import org.walkmod.javalang.compiler.symbols.ReferenceType;
import org.walkmod.javalang.compiler.symbols.Symbol;
import org.walkmod.javalang.compiler.symbols.SymbolAction;
import org.walkmod.javalang.compiler.symbols.SymbolTable;

public class RemoveUnusedSymbolsAction extends SymbolAction {

	private List siblings;

	public RemoveUnusedSymbolsAction(List container) {
		this.siblings = container;
	}

	@Override
	public void doPop(Symbol symbol, SymbolTable table) {

		Node n = symbol.getLocation();
		if (n != null) {
			Map attrs = symbol.getAttributes();

			Object reads = attrs.get(ReferencesCounterAction.READS);

			Object writes = attrs.get(ReferencesCounterAction.WRITES);

			if (reads == null && writes == null) {
				if (n instanceof MethodDeclaration) {
					removeMethod(symbol, table);
				} else if (n instanceof VariableDeclarator) {
					Node parentNode = n.getParentNode();
					if (parentNode != null) {
						if (parentNode instanceof FieldDeclaration) {
							removeField(symbol, table,
									(FieldDeclaration) parentNode);
						} else {
							removeVariable(symbol, table,
									(VariableDeclarationExpr) parentNode);
						}
					}

				} else if (n instanceof TypeDeclaration) {
					Symbol thisSymbol = table.findSymbol("this",
							ReferenceType.VARIABLE);
					if (symbol.getReferenceType().equals(ReferenceType.TYPE)
							&& thisSymbol != null && !thisSymbol.getType().equals(symbol.getType())) {
						removeType(symbol, table);
					}
				} else if (n instanceof ImportDeclaration) {
					removeImport(symbol, table);
				}
			}
		}
	}

	public List getSiblings() {
		return siblings;
	}

	public void removeImport(Symbol symbol, SymbolTable table) {
		ImportDeclaration id = (ImportDeclaration) symbol.getLocation();
		if (id.isAsterisk() || id.isStatic()) {

			String type = id.getName().toString();
			if (!id.isAsterisk()) {
				int pos = type.lastIndexOf('.');
				type = type.substring(0, pos);
			}
			List> symbols = table.findSymbolsByType(type,
					ReferenceType.TYPE);
			boolean used = false;
			List> staticElems = null;
			if (id.isStatic()) {
				staticElems = table.findSymbolsByLocation(id);
			}
			Iterator> it = symbols.iterator();
			while (it.hasNext() && !used) {
				Symbol candidate = it.next();

				if (id.isStatic()) {

					Iterator> itStatic = staticElems.iterator();
					while (itStatic.hasNext() && !used) {
						Symbol staticElem = itStatic.next();

						ReferenceType rt = staticElem.getReferenceType();
						if (rt.equals(ReferenceType.METHOD)
								|| rt.equals(ReferenceType.VARIABLE)) {
							Map attrs = staticElem
									.getAttributes();
							Object reads = attrs
									.get(ReferencesCounterAction.READS);
							Object writes = attrs
									.get(ReferencesCounterAction.WRITES);
							used = (reads != null || writes != null);
						}

					}

					if (!used) {
						Map attrs = candidate.getAttributes();
						Object reads = attrs.get(ReferencesCounterAction.READS);
						used = (reads != null);
					}
				}
			}
			if (!used) {
				remove(id);
			}
		} else {
			String type = id.getName().toString();
			// internal classes
			List> symbols = table.findSymbolsByType(type,
					ReferenceType.TYPE);
			boolean used = false;
			Iterator> it = symbols.iterator();
			while (it.hasNext() && !used) {
				Symbol next = it.next();
				Map attrs = next.getAttributes();
				Object reads = attrs.get(ReferencesCounterAction.READS);
				Object writes = attrs.get(ReferencesCounterAction.WRITES);
				used = (reads != null || writes != null);
			}
			if (!used) {
				remove(id);
			}
		}
	}

	private void remove(Object o) {
		Iterator it = siblings.iterator();
		boolean removed = false;
		while (it.hasNext() && !removed) {
			Node aux = it.next();
			if (aux == o) { // yes, by reference
				it.remove();
				removed = true;
			}
		}
	}

	public void removeMethod(Symbol symbol, SymbolTable table) {
		MethodDeclaration md = (MethodDeclaration) symbol.getLocation();

		int modifiers = md.getModifiers();
		if (ModifierSet.isPrivate(modifiers)) {
			remove(md);
		}
	}

	public void removeType(Symbol symbol, SymbolTable table) {
		TypeDeclaration td = (TypeDeclaration) symbol.getLocation();
		int modifiers = td.getModifiers();
		if (ModifierSet.isPrivate(modifiers)) {
			remove(td);
		}
	}

	public void removeVariable(Symbol symbol, SymbolTable table,
			VariableDeclarationExpr vd) {

		List vds = vd.getVars();
		if (vds.size() == 1) {
			Expression init = vds.get(0).getInit();
			if (isReadOnlyExpression(init)) {
				remove(vd.getParentNode());
			}
		} else {
			Iterator it = vds.iterator();
			boolean finish = false;
			while (it.hasNext() && !finish) {
				VariableDeclarator current = it.next();
				if (current.getId().getName().equals(symbol.getName())) {
					if (isReadOnlyExpression(current.getInit())) {
						finish = true;
						it.remove();
					}
				}
			}
		}
	}

	private boolean isReadOnlyExpression(Expression init) {
		return (init == null || init instanceof LiteralExpr || init instanceof NameExpr);
	}

	public void removeField(Symbol symbol, SymbolTable table,
			FieldDeclaration fd) {

		int modifiers = fd.getModifiers();
		if (ModifierSet.isPrivate(modifiers)) {
			List vds = fd.getVariables();
			if (vds != null) {
				Iterator it = vds.iterator();
				while (it.hasNext()) {
					VariableDeclarator vd = it.next();
					if (vd.getId().getName().equals(symbol.getName())) {
						Expression init = vd.getInit();
						if (isReadOnlyExpression(init)) {
							if (vds.size() == 1) {
								remove(fd);
							} else {
								it.remove();
							}
						}
					}
				}
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy