Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of Compiler crashes to help people report and debug #1213

Merged
merged 1 commit into from
Jan 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 20 additions & 9 deletions cruise.umple/src/UmpleInternalParser_Code.ump
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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