Added basic error and warning highlighting as well as compiler summary

This commit is contained in:
Brendan Robert 2015-07-17 01:45:18 -05:00
parent 3b4960c3de
commit 693d29952b
6 changed files with 144 additions and 43 deletions

View File

@ -24,7 +24,8 @@ public class AcmeCompiler implements CompileResult<File> {
boolean successful = false; boolean successful = false;
File compiledAsset = null; File compiledAsset = null;
Map<Integer, String> errorsAndWarnings = new LinkedHashMap<>(); Map<Integer, String> errors = new LinkedHashMap<>();
Map<Integer, String> warnings = new LinkedHashMap<>();
List<String> otherWarnings = new ArrayList<>(); List<String> otherWarnings = new ArrayList<>();
List<String> rawOutput = new ArrayList<>(); List<String> rawOutput = new ArrayList<>();
@ -39,8 +40,13 @@ public class AcmeCompiler implements CompileResult<File> {
} }
@Override @Override
public Map<Integer, String> getErrorsAndWarnings() { public Map<Integer, String> getErrors() {
return errorsAndWarnings; return errors;
}
@Override
public Map<Integer, String> getWarnings() {
return warnings;
} }
@Override @Override
@ -101,11 +107,33 @@ public class AcmeCompiler implements CompileResult<File> {
restoreSystemOutput(); restoreSystemOutput();
System.setProperty("user.dir", oldPath); System.setProperty("user.dir", oldPath);
} }
String output = baosOut.toString(); rawOutput.add("Error output:");
String errors = baosErr.toString(); extractOutput(baosErr.toString());
System.out.println("output: "+output); rawOutput.add("");
System.out.println("error: "+errors); rawOutput.add("------------------------------");
rawOutput.add("Standard output:");
extractOutput(baosOut.toString());
}
public void extractOutput(String output) throws NumberFormatException {
for (String line : output.split("\\n")) {
rawOutput.add(line);
int lineNumberStart = line.indexOf(", line") + 6;
if (lineNumberStart > 6) {
int lineNumberEnd = line.indexOf(' ', lineNumberStart+1);
int actualLineNumber = Integer.parseUnsignedInt(line.substring(lineNumberStart, lineNumberEnd).trim());
String message = line.substring(lineNumberEnd).trim();
if (line.startsWith("Error")) {
errors.put(actualLineNumber, message);
} else {
warnings.put(actualLineNumber, message);
}
} else {
if (line.trim().length() > 1) {
otherWarnings.add(line);
}
}
}
} }
public void restoreSystemOutput() { public void restoreSystemOutput() {

View File

@ -13,7 +13,9 @@ public interface CompileResult<T> {
public T getCompiledAsset(); public T getCompiledAsset();
public Map<Integer, String> getErrorsAndWarnings(); public Map<Integer, String> getErrors();
public Map<Integer, String> getWarnings();
public List<String> getOtherMessages(); public List<String> getOtherMessages();

View File

@ -18,6 +18,7 @@ import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.Event; import javafx.event.Event;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Menu; import javafx.scene.control.Menu;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab; import javafx.scene.control.Tab;
@ -200,12 +201,18 @@ public class IdeController {
@FXML @FXML
void executeClicked(ActionEvent event) { void executeClicked(ActionEvent event) {
getCurrentProgram().ifPresent(proxy -> proxy.execute()); getCurrentProgram().ifPresent(program -> {
program.execute();
updateStatusMessages(program.lastResult);
});
} }
@FXML @FXML
void testCompileClicked(ActionEvent event) { void testCompileClicked(ActionEvent event) {
getCurrentProgram().ifPresent(proxy -> proxy.test()); getCurrentProgram().ifPresent(program -> {
program.test();
updateStatusMessages(program.lastResult);
});
} }
@FXML @FXML
@ -242,4 +249,12 @@ public class IdeController {
runMenu.setDisable(hasNoItems); runMenu.setDisable(hasNoItems);
}); });
} }
private void updateStatusMessages(CompileResult lastResult) {
String message = "Compiler was " + (lastResult.isSuccessful() ? " successful" : " NOT SUCCESSFUL");
message += " -- ";
message += lastResult.getErrors().size() + " error(s) and "+lastResult.getWarnings().size()+" warning(s) reported.";
statusBar.getItems().clear();
statusBar.getItems().add(new Label(message));
}
} }

View File

@ -29,36 +29,6 @@ public class Program {
public static String CODEMIRROR_EDITOR = "/codemirror/editor.html"; public static String CODEMIRROR_EDITOR = "/codemirror/editor.html";
public void save(File newTarget) {
FileWriter writer = null;
if (newTarget == null && targetFile == null) {
return;
}
if (newTarget != null) {
targetFile = newTarget;
}
filename = targetFile.getName();
try {
writer = new FileWriter(targetFile, false);
writer.append(getValue());
writer.close();
} catch (IOException ex) {
Logger.getLogger(Program.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException ex) {
Logger.getLogger(Program.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public boolean isChanged() {
return (Boolean) codeMirror.call("isClean");
}
public static enum DocumentType { public static enum DocumentType {
applesoft(new ApplesoftHandler(), "textfile", "*.bas"), assembly(new AssemblyHandler(), "textfile", "*.a", "*.s", "*.asm"), plain(new TextHandler(), "textfile", "*.txt"), hex(new TextHandler(), "textfile", "*.bin", "*.raw"); applesoft(new ApplesoftHandler(), "textfile", "*.bas"), assembly(new AssemblyHandler(), "textfile", "*.a", "*.s", "*.asm"), plain(new TextHandler(), "textfile", "*.txt"), hex(new TextHandler(), "textfile", "*.bin", "*.raw");
@ -165,7 +135,8 @@ public class Program {
public void createEditor() { public void createEditor() {
String document = targetFile == null ? getHandler().getNewDocumentContent() : getFileContents(targetFile); String document = targetFile == null ? getHandler().getNewDocumentContent() : getFileContents(targetFile);
String optionString = buildOptions(); String optionString = buildOptions();
codeMirror = (JSObject) editor.getEngine().executeScript("CodeMirror(document.body, " + optionString + ");"); editor.getEngine().executeScript("var codeMirror = CodeMirror(document.body, " + optionString + ");");
codeMirror = (JSObject) editor.getEngine().executeScript("codeMirror");
setValue(document); setValue(document);
} }
@ -195,6 +166,37 @@ public class Program {
return ""; return "";
} }
public void save(File newTarget) {
FileWriter writer = null;
if (newTarget == null && targetFile == null) {
return;
}
if (newTarget != null) {
targetFile = newTarget;
}
filename = targetFile.getName();
try {
writer = new FileWriter(targetFile, false);
writer.append(getValue());
writer.close();
} catch (IOException ex) {
Logger.getLogger(Program.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException ex) {
Logger.getLogger(Program.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public boolean isChanged() {
return (Boolean) codeMirror.call("isClean");
}
private String buildOptions() { private String buildOptions() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("{"); builder.append("{");
@ -215,6 +217,7 @@ public class Program {
public void execute() { public void execute() {
lastResult = getHandler().compile(this); lastResult = getHandler().compile(this);
manageCompileResult(lastResult);
if (lastResult.isSuccessful()) { if (lastResult.isSuccessful()) {
getHandler().execute(lastResult); getHandler().execute(lastResult);
} }
@ -222,8 +225,23 @@ public class Program {
public void test() { public void test() {
lastResult = getHandler().compile(this); lastResult = getHandler().compile(this);
manageCompileResult(lastResult);
} }
private void manageCompileResult(CompileResult lastResult) {
editor.getEngine().executeScript("clearHighlights()");
lastResult.getWarnings().forEach((line,message) ->
editor.getEngine().executeScript("highlightLine("+line+",false,\""+escapeString(message)+"\");")
);
lastResult.getErrors().forEach((line,message) ->
editor.getEngine().executeScript("highlightLine("+line+",true,\""+escapeString(message)+"\");")
);
}
private String escapeString(Object message) {
return String.valueOf(message).replaceAll("\\\"", "&quot;");
}
public void log(String message) { public void log(String message) {
System.out.println(message); System.out.println(message);
} }

View File

@ -32,7 +32,12 @@ class TextHandler implements LanguageHandler<String> {
} }
@Override @Override
public Map<Integer, String> getErrorsAndWarnings() { public Map<Integer, String> getErrors() {
return Collections.EMPTY_MAP;
}
@Override
public Map<Integer, String> getWarnings() {
return Collections.EMPTY_MAP; return Collections.EMPTY_MAP;
} }

View File

@ -1,6 +1,7 @@
<html> <html>
<head> <head>
<title>Jace IDE</title> <title>Jace IDE</title>
<!--<script src="lib/jquery-2.1.4.min.js"></script>-->
<script src="lib/codemirror.js"></script> <script src="lib/codemirror.js"></script>
<link rel="stylesheet" href="lib/codemirror.css"/> <link rel="stylesheet" href="lib/codemirror.css"/>
</head> </head>
@ -14,6 +15,38 @@
overflow-x: hidden; overflow-x: hidden;
overflow-y: hidden; overflow-y: hidden;
} }
.line-error {
background: #FBC2C4 !important;
color: #8a1f11 !important;
}
.line-warning {
background: #F8FFAB !important;
color: #000080 !important;
}
</style> </style>
<script>
var messages = [];
function clearHighlights() {
codeMirror.eachLine(function (line) {
codeMirror.removeLineClass(line, "background", "line-error");
codeMirror.removeLineClass(line, "background", "line-warning");
});
for (var i = 0; i < messages.length; ++i) {
codeMirror.removeLineWidget(messages[i]);
}
messages = [];
}
function highlightLine(lineNumber, isError, message) {
if (isError) {
codeMirror.removeLineClass(lineNumber-1, "background", "line-warning");
}
codeMirror.addLineClass(lineNumber - 1, 'background', isError ? 'line-error' : 'line-warning');
var msg = document.createElement("div");
var text = document.createTextNode(message);
msg.appendChild(text);
var widget = codeMirror.addLineWidget(lineNumber - 1, msg, {coverGutter: false, noHScroll: true});
messages.push(widget);
}
</script>
</body> </body>
</html> </html>