diff --git a/UmpleToJava/UmpleTLTemplates/class_MethodDeclaration.ump b/UmpleToJava/UmpleTLTemplates/class_MethodDeclaration.ump index 0aedb28433..ed1a74943c 100755 --- a/UmpleToJava/UmpleTLTemplates/class_MethodDeclaration.ump +++ b/UmpleToJava/UmpleTLTemplates/class_MethodDeclaration.ump @@ -27,6 +27,12 @@ class UmpleToJava { String methodImplementationModifier = aMethod.getIsAbstract() ? " abstract" : ""; String methodName = aMethod.getName(); String methodType = aMethod.getType(); + // Fix issue 969 + if (!methodName.equals(uClass.getName())) + { + // If this is not a constructor, this method should return "void" + methodType = methodType.equals("") ? "void" : methodType; + } String customBeforeInjectionCode = GeneratorHelper.toCode(uClass.getApplicableCodeInjectionsCustomMethod("before", aMethod.getName(), aMethod.getMethodParameters())); String customAfterInjectionCode = GeneratorHelper.toCode(uClass.getApplicableCodeInjectionsCustomMethod("after", aMethod.getName(), aMethod.getMethodParameters())); String customPreconditionCode = GeneratorHelper.toCode(uClass.getApplicableCodeInjections("before", aMethod.getName()+"Precondition")); @@ -42,21 +48,6 @@ class UmpleToJava { String isList=""; String finalParams = ""; String finalParamsWithoutTypes = ""; - if(methodName.equals("main")&&methodType.equals("void")&&methodModifier.contains("public")&&methodModifier.contains("static")) - { - String exceptionHandlerPackage = ""; - if(mainMainClass!=null) - { - exceptionHandlerPackage = mainMainClass.getPackageName()+"."+mainMainClass.getName()+"."; - } - else - { - mainMainClass = uClass; - } - properMethodBody = " Thread.currentThread().setUncaughtExceptionHandler(new "+exceptionHandlerPackage+"UmpleExceptionHandler());\n"+ - " Thread.setDefaultUncaughtExceptionHandler(new "+exceptionHandlerPackage+"UmpleExceptionHandler());\n"+properMethodBody; - uClass.setHasMainMethod(true); - } StringBuilder parameters = new StringBuilder(); StringBuilder parametersWithoutTypes = new StringBuilder(); if (aMethod.hasMethodParameters()) @@ -75,6 +66,22 @@ class UmpleToJava { finalParamsWithoutTypes = parametersWithoutTypes.toString().substring(0, parametersWithoutTypes.toString().length()-2); } + if(methodName.equals("main")&&methodType.equals("void")&&methodModifier.contains("public")&&methodModifier.contains("static")&¶mType.equals("String")&&isList.equals(" [] ")&¶mName.equals("args")) + { + String exceptionHandlerPackage = ""; + if(mainMainClass!=null) + { + exceptionHandlerPackage = mainMainClass.getPackageName()+"."+mainMainClass.getName()+"."; + } + else + { + mainMainClass = uClass; + } + properMethodBody = " Thread.currentThread().setUncaughtExceptionHandler(new "+exceptionHandlerPackage+"UmpleExceptionHandler());\n"+ + " Thread.setDefaultUncaughtExceptionHandler(new "+exceptionHandlerPackage+"UmpleExceptionHandler());\n"+properMethodBody; + uClass.setHasMainMethod(true); + } + if (aMethod.numberOfComments() > 0) { append(realSb, "\n\n {0}", Comment.format("Method Javadoc",aMethod.getComments())); } append(realSb,"\n"); diff --git a/cruise.umple/src/UmpleInternalParser_CodeClass.ump b/cruise.umple/src/UmpleInternalParser_CodeClass.ump index d41227b3cf..e23346ec21 100755 --- a/cruise.umple/src/UmpleInternalParser_CodeClass.ump +++ b/cruise.umple/src/UmpleInternalParser_CodeClass.ump @@ -2719,10 +2719,6 @@ private Boolean checkIsDistributed(UmpleInterface uInterface) if (methodToken.is("methodName")) { aMethod.setName(methodToken.getValue()); - if (methodToken.getValue().equals("main")) - { - uElement.setHasMainMethod(true); - } } if (methodToken.is("parameterList")) { diff --git a/cruise.umple/test/cruise/umple/implementation/DistributedClassTest.java b/cruise.umple/test/cruise/umple/implementation/DistributedClassTest.java index 03bcdcb67e..469560302b 100644 --- a/cruise.umple/test/cruise/umple/implementation/DistributedClassTest.java +++ b/cruise.umple/test/cruise/umple/implementation/DistributedClassTest.java @@ -12,6 +12,7 @@ import org.junit.*; import cruise.umple.compiler.UmpleModel; +import cruise.umple.compiler.java.JavaClassGenerator; import cruise.umple.util.SampleFileWriter; import java.io.File; @@ -169,6 +170,16 @@ public void assertUmpleProxyFor(String umpleFile, String codeFile, String classN } } + + @After + public void tearDown() { + /* Nullify mainMainClass. It's a static variable, if we don't do this the state will + * affect the next set of JUnit tests that use mainMainClass. + */ + + JavaClassGenerator.mainMainClass = null; + } + @Test public void TestDistributableDirectivesTest1() { diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.java.txt b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.java.txt index da1dbfd2a0..cec1a42a33 100644 --- a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.java.txt +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.java.txt @@ -24,8 +24,105 @@ public class Mentor public void delete() {} - public static main(){ + public static void main(String [] args){ + Thread.currentThread().setUncaughtExceptionHandler(new UmpleExceptionHandler()); + Thread.setDefaultUncaughtExceptionHandler(new UmpleExceptionHandler()); } + public static class UmpleExceptionHandler implements Thread.UncaughtExceptionHandler + { + public void uncaughtException(Thread t, Throwable e) + { + translate(e); + if(e.getCause()!=null) + { + translate(e.getCause()); + } + e.printStackTrace(); + } + public void translate(Throwable e) + { + java.util.List result = new java.util.ArrayList(); + StackTraceElement[] elements = e.getStackTrace(); + try + { + for(StackTraceElement element:elements) + { + String className = element.getClassName(); + String methodName = element.getMethodName(); + boolean methodFound = false; + int index = className.lastIndexOf('.')+1; + try { + java.lang.reflect.Method query = this.getClass().getMethod(className.substring(index)+"_"+methodName,new Class[]{}); + UmpleSourceData sourceInformation = (UmpleSourceData)query.invoke(this,new Object[]{}); + for(int i=0;i=0&&distanceFromStart<=sourceInformation.getLength(i)) + { + result.add(new StackTraceElement(element.getClassName(),element.getMethodName(),sourceInformation.getFileName(i),sourceInformation.getUmpleLine(i)+distanceFromStart)); + methodFound = true; + break; + } + } + } + catch (Exception e2){} + if(!methodFound) + { + result.add(element); + } + } + } + catch (Exception e1) + { + e1.printStackTrace(); + } + e.setStackTrace(result.toArray(new StackTraceElement[0])); + } + //The following methods Map Java lines back to their original Umple file / line + public UmpleSourceData Mentor_main(){ return new UmpleSourceData().setFileNames("ClassTemplateTest_Generated.ump").setUmpleLines(5).setJavaLines(28).setLengths(3);} + + } + public static class UmpleSourceData + { + String[] umpleFileNames; + Integer[] umpleLines; + Integer[] umpleJavaLines; + Integer[] umpleLengths; + + public UmpleSourceData(){ + } + public String getFileName(int i){ + return umpleFileNames[i]; + } + public Integer getUmpleLine(int i){ + return umpleLines[i]; + } + public Integer getJavaLine(int i){ + return umpleJavaLines[i]; + } + public Integer getLength(int i){ + return umpleLengths[i]; + } + public UmpleSourceData setFileNames(String... filenames){ + umpleFileNames = filenames; + return this; + } + public UmpleSourceData setUmpleLines(Integer... umplelines){ + umpleLines = umplelines; + return this; + } + public UmpleSourceData setJavaLines(Integer... javalines){ + umpleJavaLines = javalines; + return this; + } + public UmpleSourceData setLengths(Integer... lengths){ + umpleLengths = lengths; + return this; + } + public int size(){ + return umpleFileNames.length; + } + } } \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.ump b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.ump index 47564596f2..700173d8ec 100644 --- a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.ump +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated.ump @@ -2,6 +2,6 @@ namespace example; class Mentor { - public static main() + public static main(String[] args) {} } diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.java.txt b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.java.txt new file mode 100644 index 0000000000..5d516e3b11 --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.java.txt @@ -0,0 +1,31 @@ +/*PLEASE DO NOT EDIT THIS CODE*/ +/*This code was generated using the UMPLE @UMPLE_VERSION@ modeling language!*/ + +package example; + +public class Mentor +{ + + //------------------------ + // MEMBER VARIABLES + //------------------------ + + //------------------------ + // CONSTRUCTOR + //------------------------ + + public Mentor() + {} + + //------------------------ + // INTERFACE + //------------------------ + + public void delete() + {} + + public void main(String [] args){ + + } + +} \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.ump b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.ump new file mode 100644 index 0000000000..17c0e21203 --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated2.ump @@ -0,0 +1,7 @@ +namespace example; + +class Mentor +{ + public main(String[] args) + {} +} \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.java.txt b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.java.txt new file mode 100644 index 0000000000..bc51472b7b --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.java.txt @@ -0,0 +1,31 @@ +/*PLEASE DO NOT EDIT THIS CODE*/ +/*This code was generated using the UMPLE ${last.version} modeling language!*/ + +package example; + +public class Mentor +{ + + //------------------------ + // MEMBER VARIABLES + //------------------------ + + //------------------------ + // CONSTRUCTOR + //------------------------ + + public Mentor() + {} + + //------------------------ + // INTERFACE + //------------------------ + + public void delete() + {} + + public static void main(){ + + } + +} \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.ump b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.ump new file mode 100644 index 0000000000..0a59673c2c --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated3.ump @@ -0,0 +1,7 @@ +namespace example; + +class Mentor +{ + public static void main() + {} +} diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.java.txt b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.java.txt new file mode 100644 index 0000000000..abdb634520 --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.java.txt @@ -0,0 +1,133 @@ +/*PLEASE DO NOT EDIT THIS CODE*/ +/*This code was generated using the UMPLE ${last.version} modeling language!*/ + +package example; + +public class Mentor +{ + + //------------------------ + // MEMBER VARIABLES + //------------------------ + + //------------------------ + // CONSTRUCTOR + //------------------------ + + public Mentor() + {} + + //------------------------ + // INTERFACE + //------------------------ + + public void delete() + {} + + public static void main(String [] args){ + Thread.currentThread().setUncaughtExceptionHandler(new UmpleExceptionHandler()); + Thread.setDefaultUncaughtExceptionHandler(new UmpleExceptionHandler()); + + } + + public void foo(){ + + } + + public static class UmpleExceptionHandler implements Thread.UncaughtExceptionHandler + { + public void uncaughtException(Thread t, Throwable e) + { + translate(e); + if(e.getCause()!=null) + { + translate(e.getCause()); + } + e.printStackTrace(); + } + public void translate(Throwable e) + { + java.util.List result = new java.util.ArrayList(); + StackTraceElement[] elements = e.getStackTrace(); + try + { + for(StackTraceElement element:elements) + { + String className = element.getClassName(); + String methodName = element.getMethodName(); + boolean methodFound = false; + int index = className.lastIndexOf('.')+1; + try { + java.lang.reflect.Method query = this.getClass().getMethod(className.substring(index)+"_"+methodName,new Class[]{}); + UmpleSourceData sourceInformation = (UmpleSourceData)query.invoke(this,new Object[]{}); + for(int i=0;i=0&&distanceFromStart<=sourceInformation.getLength(i)) + { + result.add(new StackTraceElement(element.getClassName(),element.getMethodName(),sourceInformation.getFileName(i),sourceInformation.getUmpleLine(i)+distanceFromStart)); + methodFound = true; + break; + } + } + } + catch (Exception e2){} + if(!methodFound) + { + result.add(element); + } + } + } + catch (Exception e1) + { + e1.printStackTrace(); + } + e.setStackTrace(result.toArray(new StackTraceElement[0])); + } + //The following methods Map Java lines back to their original Umple file / line + public UmpleSourceData Mentor_foo(){ return new UmpleSourceData().setFileNames("ClassTemplateTest_Generated4.ump").setUmpleLines(9).setJavaLines(35).setLengths(3);} + public UmpleSourceData Mentor_main(){ return new UmpleSourceData().setFileNames("ClassTemplateTest_Generated4.ump").setUmpleLines(5).setJavaLines(28).setLengths(3);} + + } + public static class UmpleSourceData + { + String[] umpleFileNames; + Integer[] umpleLines; + Integer[] umpleJavaLines; + Integer[] umpleLengths; + + public UmpleSourceData(){ + } + public String getFileName(int i){ + return umpleFileNames[i]; + } + public Integer getUmpleLine(int i){ + return umpleLines[i]; + } + public Integer getJavaLine(int i){ + return umpleJavaLines[i]; + } + public Integer getLength(int i){ + return umpleLengths[i]; + } + public UmpleSourceData setFileNames(String... filenames){ + umpleFileNames = filenames; + return this; + } + public UmpleSourceData setUmpleLines(Integer... umplelines){ + umpleLines = umplelines; + return this; + } + public UmpleSourceData setJavaLines(Integer... javalines){ + umpleJavaLines = javalines; + return this; + } + public UmpleSourceData setLengths(Integer... lengths){ + umpleLengths = lengths; + return this; + } + public int size(){ + return umpleFileNames.length; + } + } +} \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.ump b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.ump new file mode 100644 index 0000000000..e597b6184b --- /dev/null +++ b/cruise.umple/test/cruise/umple/implementation/java/ClassTemplateTest_Generated4.ump @@ -0,0 +1,11 @@ +namespace example; + +class Mentor +{ + public static void main(String[] args) + {} + + void foo() + { + } +} \ No newline at end of file diff --git a/cruise.umple/test/cruise/umple/implementation/java/JavaClassTemplateTest.java b/cruise.umple/test/cruise/umple/implementation/java/JavaClassTemplateTest.java index c9eaca83d0..6b5dbf02c4 100644 --- a/cruise.umple/test/cruise/umple/implementation/java/JavaClassTemplateTest.java +++ b/cruise.umple/test/cruise/umple/implementation/java/JavaClassTemplateTest.java @@ -128,10 +128,25 @@ public void Java() assertUmpleTemplateFor("java/ClassTemplateTest_Java.ump","java/ClassTemplateTest_Java.java.txt","Mentor"); } + // Tests fix for issue 969 and 986 @Test public void Generated() { + /* Test that "void" is added to a non-constructor method with no specified return type, + * and that the correct threading code is generated when "public static void main(String[] args)" is specified + */ assertUmpleTemplateFor("java/ClassTemplateTest_Generated.ump","java/ClassTemplateTest_Generated.java.txt","Mentor"); + /* + * Check that a "main" function (in the Java sense) is only detected (and accompanying threading code generated) + * when a function matches the "public static void main(String[] args)" format exactly. + */ + assertUmpleTemplateFor("java/ClassTemplateTest_Generated2.ump","java/ClassTemplateTest_Generated2.java.txt","Mentor"); + assertUmpleTemplateFor("java/ClassTemplateTest_Generated3.ump","java/ClassTemplateTest_Generated3.java.txt","Mentor"); + + // Check that void is not added twice if the user explicitly includes it in the .ump file + assertUmpleTemplateFor("java/ClassTemplateTest_Generated3.ump","java/ClassTemplateTest_Generated3.java.txt","Mentor"); + + } @Test diff --git a/cruise.umple/test/cruise/umple/test/harness/resource/TestResource.java b/cruise.umple/test/cruise/umple/test/harness/resource/TestResource.java index be6a4d90b3..cb393ce492 100755 --- a/cruise.umple/test/cruise/umple/test/harness/resource/TestResource.java +++ b/cruise.umple/test/cruise/umple/test/harness/resource/TestResource.java @@ -39,6 +39,8 @@ import cruise.umple.parser.analysis.RuleBasedParser; import cruise.umple.test.harness.compiler.JavaInternalCompiler; import cruise.umple.test.harness.compiler.interfaces.ICompiler; +import cruise.umple.test.harness.resource.TemplateGeneratedOutput; + import cruise.umple.util.SampleFileWriter; import org.junit.Assert;