Commit ea4f0ef9 authored by ISWB Prasetya's avatar ISWB Prasetya
Browse files

Improving the stand-in generator.

parent ec5e0674
package Sequenic.T3.Examples.InterfaceAndAbstract;
import java.io.IOException;
import java.util.List;
public abstract class Vehicle {
protected int x = 90 ;
......@@ -24,5 +27,11 @@ public abstract class Vehicle {
abstract public int slowdown() ;
public static int foo(int x) { return x+1 ; }
/*
protected List<Integer> m100(Vehicle[] vs, List<Vehicle> xs) throws IOException {
return null ;
}
*/
}
......@@ -16,7 +16,7 @@ implements a given abstract class. It generates a source file, then compiles
it. Complicated :) Note that in-memory generated class cannot be used during
the replay of a test suite! Hence the need to generate source code.
* configure (jar library): to auto configure T3
* configure (jar library): to auto configure T3 ... -> not used anymore.
* A jar of T3static is included, which contains a tool to do some static
analysis on Java source code. Currently, it only collect constants :D
......
......@@ -19,6 +19,7 @@ package Sequenic.T3;
import java.io.*;
import java.lang.reflect.* ;
import java.nio.file.*;
/**
* Used to generate a stand-in class, which is used to test an abstract class.
......@@ -33,50 +34,119 @@ import java.lang.reflect.* ;
*/
public class standinGenCmd {
static boolean debug = false ;
static boolean isDefault(int modifier) {
if (Modifier.isPublic(modifier) || Modifier.isPrivate(modifier) || Modifier.isProtected(modifier))
return false ;
else
return true ;
}
static String mkStandInCode(String standinName, Class abstractClass) throws Exception {
String s = "// a stand-in class for " + abstractClass + "\n";
s += "public class " + standinName + " extends " + abstractClass.getName() + "{\n" ;
// we will for not not generate the stand-in in the same package:
String s = "// package " + abstractClass.getPackage().getName() + "\n" ;
TypeVariable[] tyvars = abstractClass.getTypeParameters() ;
String tyvars_ = "" ;
if (tyvars != null && tyvars.length > 0) {
tyvars_ += "<" ;
for (int k=0; k<tyvars.length ; k++) {
if(k>0) tyvars_ += "," ;
tyvars_ += tyvars[k].toString() ;
}
tyvars_ += ">" ;
}
s += "// a stand-in class for " + abstractClass + "\n";
s += "public class " + standinName + tyvars_
+ " extends " + abstractClass.getName() + tyvars_
+ " {\n" ;
// generate code for constructors
Constructor[] cons = abstractClass.getDeclaredConstructors() ;
if (cons.length > 0) s += " // constructors:\n" ;
for (Constructor co : cons) {
int flag = co.getModifiers() ;
// for now ignoring abstract constructors:
if (isDefault(flag)) continue ;
if (Modifier.isPublic(flag) || Modifier.isProtected(flag)) {
String modifier = "public" ;
if ( Modifier.isProtected(flag)) modifier = "protected" ;
// generating the header
Type[] tys = co.getGenericParameterTypes() ;
s += " public " + standinName + "(" ;
s += " " + modifier + " " + standinName + "(" ;
for (int k=0; k<tys.length; k++) {
if (k>0) s += ", " ;
s += tys[k].getTypeName() + " x" + k ;
}
s += ") throws Exception { " ;
s += "super(" ;
for (int k=0; k<tys.length;k++) {
if (k>0) s += ", " ;
s += "x" + k ;
s += ")" ;
// exception list:
Class[] excs = co.getExceptionTypes() ;
if (excs!=null && excs.length>0) {
s += " throws " ;
int k=0 ;
for (Class e : excs) {
if (k>0) s += ", " ;
s += e.getName() ;
k++;
}
}
s += " {" ;
// the body:
if (Modifier.isAbstract(flag)) {
s += " throw new UnsupportedOperationException() ; " ;
}
s += ") ; }\n" ;
else {
s += " super(" ;
for (int k=0; k<tys.length;k++) {
if (k>0) s += ", " ;
s += "x" + k ;
}
s += ") ;" ;
}
s += "}\n" ;
}
}
// generate code for the methods...
// still not complete if the class has an abstract inherited method; TODO!
Method[] methods = abstractClass.getDeclaredMethods() ;
if (methods.length > 0) s += " // methods:\n" ;
for (Method m : methods) {
int flag = m.getModifiers() ;
// for now ignoring abstract constructors:
if (isDefault(flag)) continue ;
// we won't create a wrapper for static methods; G2 will target them directly anyway
if (Modifier.isStatic(flag)) continue ;
// currently ignoring default method, which require this class to be in the same package; TODO!
if (Modifier.isAbstract(flag) && (Modifier.isPublic(flag) || Modifier.isProtected(flag))) {
if (Modifier.isPublic(flag) || Modifier.isProtected(flag)) {
// generate the header:
String modifier = "public" ;
if ( Modifier.isProtected(flag)) modifier = "protected" ;
s += " " + modifier ;
Type[] tys = m.getGenericParameterTypes() ;
Type retty = m.getGenericReturnType() ;
Class[] excs = m.getExceptionTypes() ;
if (Modifier.isStatic(flag)) s += " static " ;
if (Modifier.isPublic(flag)) s += " public " ;
if (Modifier.isProtected(flag)) s += " protected " ;
s += retty.getTypeName() + " " + m.getName() + "(" ;
s += " " + retty.getTypeName() + " " + m.getName() + "(" ;
for (int k=0; k<tys.length; k++) {
if (k>0) s += ", " ;
s += tys[k].getTypeName() + " x" + k ;
}
s += ") " ;
s += ")" ;
// exception list:
Class[] excs = m.getExceptionTypes() ;
if (excs!=null && excs.length>0) {
s += "throws " ;
s += " throws " ;
int k=0 ;
for (Class e : excs) {
if (k>0) s += ", " ;
......@@ -84,21 +154,21 @@ public class standinGenCmd {
k++;
}
}
s += " { " ;
String retty_ = retty.getTypeName() ;
String ret = " return null " ;
String[] numeric = { "byte", "short", "int" , "long" , "float", "double" } ;
for (int k=0; k<numeric.length; k++) if (retty_.equals(numeric[k])) ret = " return 0 " ;
if (retty_.equals("boolean")) ret = " return false " ;
if (retty_.equals("char")) ret = " return \'0\' " ;
s += ret ;
s += " ; }\n" ;
if (Modifier.isAbstract(flag)) {
s += " throw new UnsupportedOperationException() ; " ;
}
else {
s += " return super." + m.getName() + "(" ;
for (int k=0; k<tys.length;k++) {
if (k>0) s += ", " ;
s += "x" + k ;
}
s += ") ;" ;
}
s += " }\n" ;
}
}
}
s += "}" ;
return s ;
}
......@@ -107,11 +177,9 @@ public class standinGenCmd {
/**
* Save the content in the file.
*/
static private void save(File file, String content) throws Exception {
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close();
static private void save(String filename, String content) throws IOException {
Path path = Paths.get(filename);
Files.write(path, content.getBytes());
}
......@@ -127,17 +195,17 @@ public class standinGenCmd {
String standInName = absclass.getSimpleName() + "_StandIn" ;
//String srcpath = "./src" ;
String filename = srcpath + "/" + standInName + ".java" ;
File file = new File(filename);
String code = mkStandInCode(standInName,absclass) ;
System.out.println(code);
if (debug) System.err.println(code);
// if (file.exists()) return ; well just overwrite
/*
save(file, mkStandInCode(standInName,absclass)) ;
save(filename,code) ;
System.err.println("** a stand-in " + filename + " is created.") ;
if(compileCmd == null) return ;
compileCmd += " " + filename ;
System.err.println("** about to execute: " + compileCmd) ;
Process p = Runtime.getRuntime().exec(compileCmd);
......@@ -151,7 +219,7 @@ public class standinGenCmd {
}
System.err.println("** a stand-in " + filename + " is compiled.") ;
*/
}
/**
......@@ -160,9 +228,16 @@ public class standinGenCmd {
* arg[2] : javac command to compile, e.g. javac -cp bla
*/
public static void main(String[] args) throws Exception {
//generateStandIn(args[0],args[1],args[2]) ;
generateStandIn("Sequenic.T3.Examples.InterfaceAndAbstract.Vehicle","~/tmp/t3/standins","javac -cp ./bin:../t3/bin") ;
// generateStandIn("Sequenic.T3.Examples.Abstractx.Vehicle",".","c:/apps/Java/jdk1.8u31/bin/javac -version") ;
if (args.length == 2)
generateStandIn(args[0],args[1],null);
else
generateStandIn(args[0],args[1],args[2]) ;
/*
generateStandIn(
"Sequenic.T3.Examples.InterfaceAndAbstract.Vehicle",
"/Users/iswbprasetya/tmp/t3/standins",
"javac -cp ./bin:../t3/bin") ;
*/
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment