Skip to content

Commit

Permalink
Merge pull request #1213 from umple/ImproveCompilerCrashHandling
Browse files Browse the repository at this point in the history
Improve handling of Compiler crashes to help people report and debug
  • Loading branch information
TimLethbridge committed Jan 31, 2018
2 parents c09c816 + 61bd552 commit ed42901
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 35 deletions.
29 changes: 20 additions & 9 deletions cruise.umple/src/UmpleInternalParser_Code.ump
Expand Up @@ -100,17 +100,28 @@ class UmpleInternalParser

public ParseResult analyze(boolean shouldGenerate)
{
setParseResult(parser.getParseResult());
setRootToken(parser.getRootToken());
analyzeAllTokens(getRootToken());
postTokenAnalysis();
secondPostTokenAnalysis();
//add analysis here!!! xx.validateStateMachineGuardConstraints(model);
checkDefaultedNameConflict();
try {
setParseResult(parser.getParseResult());
setRootToken(parser.getRootToken());
analyzeAllTokens(getRootToken());
postTokenAnalysis();
secondPostTokenAnalysis();
//add analysis here!!! xx.validateStateMachineGuardConstraints(model);
checkDefaultedNameConflict();
}
catch (Exception ex)
{
setFailedPosition(new Position("",0,0,0),9100,
"Could not analyze Umple model. Please report an issue with this entire message and your input code to Umple developers.\nStack Trace Follows.\n"+
cruise.umple.util.ExceptionDumper.dumpCompilerError(ex));
}

if (shouldGenerate && getParseResult().getWasSuccess())
{
model.generate();
String generatorError = model.generate();
if(generatorError != null) {
setFailedPosition(new Position("",0,0,0),9200,generatorError);
}
}
return getParseResult();
}
Expand Down Expand Up @@ -163,7 +174,7 @@ class UmpleInternalParser
//------------------------

// When an error occurs, set the failed position and mark the compile as NOT successful
private void setFailedPosition(Position position, int errorCode, String... messages)
public void setFailedPosition(Position position, int errorCode, String... messages)
{
//getParseResult().setWasSuccess(false);

Expand Down
49 changes: 38 additions & 11 deletions cruise.umple/src/Umple_Code.ump
Expand Up @@ -231,19 +231,44 @@ class UmpleModel
return analyzers.get(name);
}
/*
* Creates a new parser, loads the input, parses, then analyses
* Creates a new parser, loads the input, parses, then analyses; analyser generates
*/
public void run()
{
boolean failed = false;
String input;
RuleBasedParser parser = new RuleBasedParser();

UmpleParser analyzer = new UmpleInternalParser("UmpleInternalParser",this,parser);
ParseResult result = parser.parse( new File(umpleFile.getPath() + File.separator + umpleFile.getFileName()), this.linkedFiles.toArray(new File[0]) );
UmpleInternalParser analyzer = new UmpleInternalParser("UmpleInternalParser",this,parser);
ParseResult result = null;

try {
result = parser.parse(
new File(umpleFile.getPath() + File.separator + umpleFile.getFileName()),
this.linkedFiles.toArray(new File[0]));
}
catch (Exception ex)
{
result = parser.parse("classDefinition",""); // Fake to ensure can proceed
lastResult = result;
result.addErrorMessage(new ErrorMessage(9000,new Position("",0,0,0),
"Could not parse Umple model. Please report an issue with this entire message and your input code to Umple developers. \nStack dump follows\n"+cruise.umple.util.ExceptionDumper.dumpCompilerError(ex)
));
throw new UmpleCompilerException(result.toString(),null);
}
catch (StackOverflowError ex)
{
result = parser.parse("classDefinition",""); // Fake to ensure can proceed
lastResult = result;
result.addErrorMessage(new ErrorMessage(9000,new Position("",0,0,0),
"Could not parse Umple model. Please report an issue with this entire message and your input code to Umple developers. \nStack Overflow in Parsing.\n"+cruise.umple.util.ExceptionDumper.dumpCompilerError(ex)
));
throw new UmpleCompilerException(result.toString(),null);
}

this.extractAnalyzersFromParser(parser);

failed = !result.getWasSuccess();
failed = failed || !result.getWasSuccess();
lastResult = result;

if(!failed)
Expand Down Expand Up @@ -300,33 +325,35 @@ class UmpleModel
/*
* Generates the actual code for each generation target
*/
public void generate()
public String generate()
{
String lang="Unknown";
applyFilter(null);
boolean foundGenerator;
parsingTime = System.currentTimeMillis()/1000.0;
try
{
for (GenerateTarget target : getGenerates())
{
CodeGenerator generator = newGenerator(target.getLanguage());
lang=target.getLanguage();
CodeGenerator generator = newGenerator(lang);
generator.setOutput(target.getPath());
CodeBlock.languageUsed = target.getLanguage();
CodeBlock.languageUsed = lang;
for (String subopt : target.getSuboptions()) {
generator.setSuboption(subopt);
}
gTime1 = System.currentTimeMillis()/1000.0;
generator.generate();
gTime2 = System.currentTimeMillis()/1000.0;
Double gTime = gTime2 - gTime1;
hashMap.put(target.getLanguage(),(String.valueOf(gTime)));
hashMap.put(lang,(String.valueOf(gTime)));
}
return null; // generators all worked
}
catch (Exception ex)
{
System.err.println("Code Generator error. Unable to generate code: Stack Trace Follows.");
cruise.umple.util.ExceptionDumper.dumpCompilerError(ex);
System.exit(-1);
return("Could not generate "+lang+"\nPlease report an issue with this entire message and your input code to Umple developers.\nStack Trace Follows.\n"+
cruise.umple.util.ExceptionDumper.dumpCompilerError(ex));
}
}

Expand Down
6 changes: 6 additions & 0 deletions cruise.umple/src/en.error
Expand Up @@ -208,6 +208,7 @@
2001: 5, "http://cruise.eecs.uottawa.ca/umple/W20xxErrorinEmbeddedCode.html", Error in Java embedded in Umple: '{0}' ;
2002: 5, "http://cruise.eecs.uottawa.ca/umple/W20xxErrorinEmbeddedCode.html", Error in C++ embedded in Umple: '{0}' ;


# Warning messages related to distributed systems

7002: 4, "http://cruise.eecs.uottawa.ca/umple/AssociationDistToNonDistributed.html", Distributed class '{0}' has an association with non-distributed class '{1}'. ;
Expand All @@ -218,6 +219,11 @@
8001: 1, "http://cruise.eecs.uottawa.ca/umple/PageBeingDeveloped.html", Debug error : '{0}' ;
8005: 5, "http://cruise.eecs.uottawa.ca/umple/PageBeingDeveloped.html", Debug warning : '{0}' ;

# Messages related to code generator
9000: 1, "http://cruise.eecs.uottawa.ca/umple/PageBeingDeveloped.html", Compiler Error (Parsing). {0} ;
9100: 1, "http://cruise.eecs.uottawa.ca/umple/PageBeingDeveloped.html", Compiler Error (Analysis). {0} ;
9200: 1, "http://cruise.eecs.uottawa.ca/umple/PageBeingDeveloped.html", Compiler Error (Generation). {0} ;

# Message to emit when you are parsing a construct but are not yet processing it in a sensible way/
9999: 5, "http://cruise.eecs.uottawa.ca/umple/W9999FeatureUnderDevelopment.html", Feature under development. '{0}' found and ignored. processed as: '{1}' ;

Expand Down
38 changes: 23 additions & 15 deletions cruise.umple/src/util/Util_Code.ump
Expand Up @@ -84,30 +84,41 @@ class ExceptionDumper {
depend java.nio.file.Path;
depend java.nio.file.Paths;

public static void dumpCompilerError(Exception ex) {
String generatedSourcePath = System.getenv("GeneratedSourcePath");
public static String dumpCompilerError(Throwable ex) {
String generatedMessage = "";
String generatedSourcePath = System.getenv("GeneratedSourcePath");
String sourcePathType="GeneratedSourcePath that has been set to ";
if (generatedSourcePath == null) {
System.err.println("To locate the error in the original Umple source, set GeneratedSourcePath to root directory where the generated Java is located:\ne.g. setenv GeneratedSourcePath ~/umple/cruise.umple/src-gen-umple/");
String homedir = System.getenv("HOME");
if(homedir != null &&
(new File(homedir+"/umple/cruise.umple/src-gen-umple/cruise/umple/core/")).exists()) {
// Use default generated source path
generatedSourcePath = homedir+"/umple/cruise.umple/src-gen-umple/";
sourcePathType="default GeneratedSourcePath ";
}
else {
generatedMessage += "To locate the error in the Umple source, set GeneratedSourcePath to root directory where the generated Java is located:\ne.g. setenv GeneratedSourcePath ~/umple/cruise.umple/src-gen-umple/\n";
}
}
else {
System.err.println("Using GeneratedSourcePath="+generatedSourcePath);
if (generatedSourcePath != null) {
generatedMessage +="Using "+sourcePathType+generatedSourcePath+"\n";
}
System.err.println("Exception "+ex.getClass().getName()+" in");
generatedMessage +="Exception "+ex.getClass().getName()+" in\n";

StackTraceElement [] st = ex.getStackTrace();
StackTraceElement ust = null;
for (int i=0;i<st.length;i++) {
System.err.println(" at "+st[i].toString());
int dumpLimit = st.length;
if (dumpLimit > 30) dumpLimit = 30;
for (int i=0;i<dumpLimit;i++) {
generatedMessage +=" at "+st[i].toString()+"\n";
if(generatedSourcePath != null) {
ust = javaToUmpleStackTrace(st[i], generatedSourcePath);
if(ust != null) {
System.err.println(" => "+ust.getFileName()+":"+ust.getLineNumber());
generatedMessage +=" => "+ust.getFileName()+":"+ust.getLineNumber()+"\n";
}
else {
System.err.println(" => Unknown umple file - please ask developers to debug Util_code.ump javaToUmpleStackTrace");
}
}
}
return generatedMessage;
}

// Translate the java stack trace line information into the corresponding Umple line
Expand Down Expand Up @@ -156,9 +167,6 @@ class ExceptionDumper {
sc = new Scanner(new BufferedReader(new FileReader(pathToJavaFile.toFile())));
}
catch (FileNotFoundException fne) {
sc = null;
System.err.println(" !! Could not open "
+ pathToJavaFile + "\nTry setting environment variable GeneratedSourcePath to path containing file");
return null;
}
}
Expand Down

0 comments on commit ed42901

Please sign in to comment.