Difference between revisions of "Discovering Valid Java Main Methods"

From AtlasWiki
Jump to: navigation, search
(Created page with "TODO <br /><center>Back to Learning Atlas</center>")
 
Line 1: Line 1:
TODO
+
The [https://ensoftcorp.github.io/toolbox-commons/ Toolbox Commons] project defines an <code>Analyzer</code> interface that encapsulates the logic for traversing a program graph to extract an "envelope" (a subgraph that is either empty if a property is satisfied or non-empty containing the necessary information to locate the violation of the property). Analyzers encapsulate their descriptions, assumptions, analysis context, and analysis logic.  Of course you can define your own "Analyzer" simply by writing a program with your analysis logic, but we find this abstraction helps keep code organized when contributing to a toolbox project.
 +
 
 +
<pre>
 +
public class DiscoverMainMethods extends Analyzer {
 +
 
 +
@Override
 +
public String getName(){
 +
return "Discover Main Methods";
 +
}
 +
 +
@Override
 +
public String getDescription() {
 +
return "Finds methods named \"main\" that are public static void methods that take a String array.";
 +
}
 +
 
 +
@Override
 +
public String[] getAssumptions() {
 +
return new String[]{"All main methods are named \"main\".",
 +
"All main methods are public.",
 +
"All main methods are static.",
 +
"All main methods return void.",
 +
"All main methods take a single parameter of a String array."};
 +
}
 +
 
 +
@Override
 +
protected Q evaluateEnvelope() {
 +
// Step 1) select nodes from the index that are marked as public, static, methods
 +
Q mainMethods = context.nodesTaggedWithAll(Node.IS_PUBLIC, Node.IS_STATIC, Node.METHOD);
 +
 +
// Step 2) select nodes from the public static methods that are named "main"
 +
mainMethods = mainMethods.selectNode(Node.NAME, "main");
 +
 
 +
// Step 3) filter out methods that are not void return types
 +
mainMethods = mainMethods.intersection(Common.stepFrom(Common.edges(Edge.RETURNS), Common.types("void")));
 +
 +
// Step 4) filter out methods that do not take exactly one parameter
 +
Q paramEdgesInContext = context.edgesTaggedWithAny(Edge.PARAM).retainEdges();
 +
// methods with no parameteres will not have a PARAM edge
 +
Q methodsWithNoParams = mainMethods.difference(Common.stepFrom(paramEdgesInContext, Common.stepTo(paramEdgesInContext, mainMethods)));
 +
// methods with 2 or more params will have at least one edge with PARAMETER_INDEX == 1 (index 0 is the first parameter)
 +
Q methodsWithTwoOrMoreParams = Common.stepFrom(paramEdgesInContext, Common.stepTo(paramEdgesInContext, mainMethods).selectNode(Node.PARAMETER_INDEX, 1));
 +
mainMethods = mainMethods.difference(methodsWithNoParams, methodsWithTwoOrMoreParams);
 +
 +
// Step 5) filter out methods that do not take a String array
 +
// get the 1-dimensional String array type
 +
Q stringArrays = Common.stepFrom(Common.edges(Edge.ELEMENTTYPE), Common.typeSelect("java.lang","String"));
 +
Q oneDimensionStringArray = stringArrays.selectNode(Node.DIMENSION, 1);
 +
Q mainMethodParams = CommonQueries.methodParameter(mainMethods, 0);
 +
Q validMethodParams = mainMethodParams.intersection(Common.stepFrom(Common.edges(Edge.TYPEOF), oneDimensionStringArray));
 +
mainMethods = Common.stepFrom(paramEdgesInContext, validMethodParams);
 +
 
 +
return mainMethods;
 +
}
 +
 +
}
 +
</pre>
  
 
<br /><center>Back&nbsp;to&nbsp;[[Learning Atlas]]</center>
 
<br /><center>Back&nbsp;to&nbsp;[[Learning Atlas]]</center>

Revision as of 15:41, 5 February 2015

The Toolbox Commons project defines an Analyzer interface that encapsulates the logic for traversing a program graph to extract an "envelope" (a subgraph that is either empty if a property is satisfied or non-empty containing the necessary information to locate the violation of the property). Analyzers encapsulate their descriptions, assumptions, analysis context, and analysis logic. Of course you can define your own "Analyzer" simply by writing a program with your analysis logic, but we find this abstraction helps keep code organized when contributing to a toolbox project.

public class DiscoverMainMethods extends Analyzer {

	@Override 
	public String getName(){
		return "Discover Main Methods";
	}
	
	@Override
	public String getDescription() {
		return "Finds methods named \"main\" that are public static void methods that take a String array.";
	}

	@Override
	public String[] getAssumptions() {
		return new String[]{"All main methods are named \"main\".", 
							"All main methods are public.",
							"All main methods are static.",
							"All main methods return void.",
							"All main methods take a single parameter of a String array."};
	}

	@Override
	protected Q evaluateEnvelope() {
		// Step 1) select nodes from the index that are marked as public, static, methods
		Q mainMethods = context.nodesTaggedWithAll(Node.IS_PUBLIC, Node.IS_STATIC, Node.METHOD);
		
		// Step 2) select nodes from the public static methods that are named "main"
		mainMethods = mainMethods.selectNode(Node.NAME, "main");

		// Step 3) filter out methods that are not void return types
		mainMethods = mainMethods.intersection(Common.stepFrom(Common.edges(Edge.RETURNS), Common.types("void")));
		
		// Step 4) filter out methods that do not take exactly one parameter
		Q paramEdgesInContext = context.edgesTaggedWithAny(Edge.PARAM).retainEdges();
		// methods with no parameteres will not have a PARAM edge
		Q methodsWithNoParams = mainMethods.difference(Common.stepFrom(paramEdgesInContext, Common.stepTo(paramEdgesInContext, mainMethods)));
		// methods with 2 or more params will have at least one edge with PARAMETER_INDEX == 1 (index 0 is the first parameter)
		Q methodsWithTwoOrMoreParams = Common.stepFrom(paramEdgesInContext, Common.stepTo(paramEdgesInContext, mainMethods).selectNode(Node.PARAMETER_INDEX, 1));
		mainMethods = mainMethods.difference(methodsWithNoParams, methodsWithTwoOrMoreParams);
		
		// Step 5) filter out methods that do not take a String array
		// get the 1-dimensional String array type
		Q stringArrays = Common.stepFrom(Common.edges(Edge.ELEMENTTYPE), Common.typeSelect("java.lang","String"));
		Q oneDimensionStringArray = stringArrays.selectNode(Node.DIMENSION, 1);
		Q mainMethodParams = CommonQueries.methodParameter(mainMethods, 0);
		Q validMethodParams = mainMethodParams.intersection(Common.stepFrom(Common.edges(Edge.TYPEOF), oneDimensionStringArray));
		mainMethods = Common.stepFrom(paramEdgesInContext, validMethodParams);

		return mainMethods;
	}
	
}

Back to Learning Atlas