Commit a0d06327 authored by Leonard Faecke's avatar Leonard Faecke
Browse files

* Restructured analysis to traversing the tree

+ Added documentation comments
parent 76c40d6e
Loading
Loading
Loading
Loading
+163 −28
Original line number Diff line number Diff line
@@ -15,12 +15,9 @@ import com.google.common.base.Stopwatch;

import de.ugoe.cs.swe.common.MiscTools;
import de.ugoe.cs.swe.common.logging.LoggingInterface;
import de.ugoe.cs.swe.tTCN3.FunctionDef;
import de.ugoe.cs.swe.tTCN3.ModuleDefinition;
import de.ugoe.cs.swe.tTCN3.TTCN3File;
import de.ugoe.cs.swe.tTCN3.TTCN3Module;
//TODO: inefficient, but I currently don't want to change imports all the time
import de.ugoe.cs.swe.tTCN3.*;
import de.ugoe.cs.swe.tTCN3.impl.*;

public class UsageAnalyzer implements Callable<TTCN3Usage> {
	private final Resource resource;
@@ -76,7 +73,10 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
			//...or with a loop
			
			
			countDefinitions(module, output);
			//countDefinitions(module, output);
			analyzeModule(module, output);
			
			
		}

		stopwatch.stop();
@@ -89,27 +89,25 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
	}


	/**
	 * Counts all definitions within a module.
	 * Currently obsolete. Replaced by manual tree traversal
	 * @param module The module to be analyzed
	 * @param output The TTCN3Usage to save the output to
	 */
	private void countDefinitions(TTCN3Module module, TTCN3Usage output) {
		System.out.println("Counting Definitions");
		System.out.println("Analyzing module definitions");
		List<ModuleDefinition> definitions = EcoreUtil2.getAllContentsOfType(module, ModuleDefinition.class);
		output.getOutput().put("TotalDef", definitions.size());
		
		Set<Class<?>> toAnalyze = new HashSet<Class<?>>();
		for (ModuleDefinition d : definitions) {
			String eClassName = d.getDef().eClass().getName();
			if(output.getOutput().containsKey(eClassName)) {
				output.getOutput().put(eClassName, output.getOutput().get(eClassName) + 1);
			} else {
				output.getOutput().put(eClassName, 1);
			}
			
			//can't cast correctly dynamically? -> add to set, then analyze all manually using getAllContentsOfType
			addToOutput(output, eClassName);
			
			toAnalyze.add(d.getDef().eClass().getInstanceClass());
		}
		
		//How to generalize? Dynamic casting [d.getDef().eClass().getInstanceClass() c = (d.getDef().eClass().getInstanceClass()) d] doesn't seem to work
		//Perhaps some list of classes kept globally, easy to change and append?
		if(toAnalyze.contains(ConstDef.class)) {
			countConstants(module, output);
			toAnalyze.remove(ConstDef.class);
@@ -119,7 +117,7 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
			toAnalyze.remove(FunctionDef.class);
		}
		if(toAnalyze.size() > 0) {
			System.out.println("Unanalyzed definitions:");
			System.out.println("Unanalyzed definition types:");
			for(Class<?> a : toAnalyze) {
				System.out.println(a);
			}
@@ -127,14 +125,20 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
		System.out.println("Definitions done");
	}
	
	/**
	 * Counts the total amount and types of constant in a module.
	 * Currently obsolete. Replaced by analyzeConstDef
	 * @param module The module to be analyzed
	 * @param output The TTCN3Usage to save the output to
	 */
	private void countConstants(TTCN3Module module, TTCN3Usage output) {
		System.out.println("Counting constants");
		System.out.println("Analyzing constants");
		List<ConstDef> c = EcoreUtil2.getAllContentsOfType(module, ConstDef.class); //not very efficient
		if(c.size() > 0) { //technically not necessary, as long as this function is called in count definitions
			for(ConstDef constant : c) {
				String name = "Constant:" + constant.getType().getPre(); //Added "Constant:" to identifier for better readability of output
				if(constant.getType().getPre() == null) {
					name = "Constant:Non-Primitive";
					name = "Constant:non-primitive";
				}
				addToOutput(output, name);
			}
@@ -142,21 +146,27 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
		System.out.println("Constants done");
	}
	
	/**
	 * Analyzed functions on parameter and return value data.
	 * Currently obsolete. Replaced by manual tree traversal
	 * @param module The module to be analyzed
	 * @param output The TTCN3Usage to save the output to
	 */
	private void analyzeFunctions(TTCN3Module module, TTCN3Usage output) {
		System.out.println("Counting functions");
		System.out.println("Analyzing functions");
		List<FunctionDef> f = EcoreUtil2.getAllContentsOfType(module, FunctionDef.class);
		if(f.size() > 0) {
			for(FunctionDef function : f) {
				
				String fName = function.getName();
				System.out.println("Analyzing function: " + fName);
				
				// Return type:
				String id = "FunctionReturn:";
				//There is both Return:void and Return:null -> null is non primitive?
				//If type.pre == "null" is non primitive, how to get? -> now only marked as "non-primitive" (is more information even useful?)
				if(function.getReturnType() != null) {
					if(function.getReturnType().getType().getPre() == null) 
						id += "Non-Primitive";
						//System.out.println("Unknown: " +function.getReturnType().getType().eClass().getInstanceClassName());
					else id += function.getReturnType().getType().getPre();
					if(function.getReturnType().getType().getPre() == null) {
							id += "non-primitive";
					} else id += function.getReturnType().getType().getPre();
				} else {
					id += "void";
				}
@@ -184,21 +194,146 @@ public class UsageAnalyzer implements Callable<TTCN3Usage> {
				}
				addToOutput(output, id);
				
				//function statements
				/*
				StatementBlock statements = function.getStatement();
				if(statements != null) {
					int size = statements.getDef().size();
					System.out.println("Def in function:" + size);
					addToOutput(output, size + "DefInFunc");
					for(FunctionDefList defList : statements.getDef()) {
						if(defList.getLocDef() != null && defList.getLocDef().getConstDef() != null)
						System.out.println("DefPre:" + defList.getLocDef().getConstDef().getType().getPre());
						
					}
					size = statements.getStat().size();
					System.out.println("Stat in function:" + size);
					addToOutput(output, size + "StatInFunc");
					if(size != 0) {
						
					}
				} else { //can't happen
					System.out.println("Empty function");
				}
				*/
				
				System.out.println("Current function done");
			}
		}
		System.out.println("Functions done");
	}
	
	
	/**
	 * Add one to the given identifier in the output
	 * @param output The TTCN3Usage to add to.
	 * @param identifier The identifier to add to
	 */
	private void addToOutput(TTCN3Usage output, String identifier) {
		addNToOutput(output, identifier, 1);
	}
	
	
	/**
	 * Add n to the given identifier in the output
	 * @param output The TTCN3Usage to add to.
	 * @param identifier The identifier to add to
	 * @param n The number to add to the output to. Cannot be negative.
	 */
	private void addNToOutput(TTCN3Usage output, String identifier, int n) {
		if(output.getOutput().containsKey(identifier)) {
			output.getOutput().replace(identifier, output.getOutput().get(identifier) + 1);
			output.getOutput().replace(identifier, output.getOutput().get(identifier) + n);
		} else {
			output.getOutput().put(identifier, n);
		}
	}
	
	/**
	 * Analyzes a module on its content
	 * @param module The module to be analyzed
	 * @param output The TTCN3Usage to write the output to
	 */
	private void analyzeModule(TTCN3Module module, TTCN3Usage output) {
		if(module.getDefs() == null) {
			System.out.println("No definitions in module " + module.getName());
			return;
		}
		EList<ModuleDefinition> defs = module.getDefs().getDefinitions();
		for(ModuleDefinition def : defs) {
			if(def.getDef().getClass() == ConstDefImpl.class) {
				analyzeConstDef((ConstDef) def.getDef(), output);
			} else if (def.getDef().getClass() == FunctionDefImpl.class) {
				analyzeFunctionDef((FunctionDef) def.getDef(), output);
			} else {
			output.getOutput().put(identifier, 1);
				System.out.println("Unanalyzed: " + def.getDef().getClass());
			}
		}
	}
	
	/**
	 * Analyzes a constant defined in a module
	 * @param con The constant to be analyzed
	 * @param output The TTCN3Usage to write the output to
	 */
	private void analyzeConstDef(ConstDef con, TTCN3Usage output) {
		System.out.println("Analyzing constant");
		if(con.getType().getPre() == null) {
			//Sometimes still null?
			addToOutput(output, "Const:Non-Primitive:" + con.getType().getRef().getHead().getName());
			addToOutput(output, "Const:Non-Primitive");
		} else {
			addToOutput(output, "Const:" + con.getType().getPre());
		}
	}
	
	/**
	 * Analyzes a function defined in a module.
	 * Counts parameters and return values
	 * @param fun The function to be analyzed
	 * @param output The TTCN3Usage to write the output to
	 */
	private void analyzeFunctionDef(FunctionDef fun, TTCN3Usage output) {
		System.out.println("Analyzing function");
		
		String fName = fun.getName();
		System.out.println("Analyzing function: " + fName);
		
		// Return type:
		String id = "FunctionReturn:";
		if(fun.getReturnType() != null) {
			if(fun.getReturnType().getType().getPre() == null) {
					id += "Non-Primitive";
					addToOutput(output, id + ":" + fun.getReturnType().getType().getRef().getHead());
			} else id += fun.getReturnType().getType().getPre();
		} else {
			id += "void";
		}
		addToOutput(output, id);
		
		// Parameters per function and types:
		if(fun.getParameterList() != null) {
			EList<FunctionFormalPar> params = fun.getParameterList().getParams();
			for(FunctionFormalPar p : params) {
				id = "FunctionParam:";
				if(p.getValue() == null) {
					id += "NoVal";
				} else {
					if(p.getValue().getType().getPre() == null) {
						id += "Non-Primitive";
						addToOutput(output, id + ":" + p.getValue().getType().getRef().getHead());
					} else {
						id += p.getValue().getType().getPre();
					}
				}
				addToOutput(output, id);
			}
			id = fun.getParameterList().getParams().size()+"ParamsInFunction";
		} else {
			id = "0ParamsInFunction";
		}
		addToOutput(output, id);
	}
	
	@Override
	public TTCN3Usage call() throws Exception {
		return analyze();