Skip to content
Merged
21 changes: 8 additions & 13 deletions app/src/processing/app/ui/Editor.java
Original file line number Diff line number Diff line change
Expand Up @@ -3119,20 +3119,15 @@ public void updateEditorStatus() {


/**
* @return the Problem for the first error or warning on 'line'
* @return the Problem for the most relevant error or warning on 'line',
* defaults to the first error, if there are no errors first warning.
*/
Problem findProblem(int line) {
int currentTab = getSketch().getCurrentCodeIndex();
return problems.stream()
.filter(p -> p.getTabIndex() == currentTab)
.filter(p -> {
int pStartLine = p.getLineNumber();
int pEndOffset = p.getStopOffset();
int pEndLine = textarea.getLineOfOffset(pEndOffset);
return line >= pStartLine && line <= pEndLine;
})
.findFirst()
.orElse(null);
protected Problem findProblem(int line) {
List<Problem> problems = findProblems(line);
for (Problem p : problems) {
if (p.isError()) return p;
}
return problems.isEmpty() ? null : problems.get(0);
}


Expand Down
2 changes: 2 additions & 0 deletions build/shared/lib/languages/PDE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ editor.status.missing.right_paren = Missing right parenthesis ")"
editor.status.missing.left_curly_bracket = Missing left curly bracket "{"
editor.status.missing.right_curly_bracket = Missing right curly bracket "}"
editor.status.missing.add = Consider adding "%s"
editor.status.bad_curly_quote = Curly quotes like %s don't work. Use straight quotes. Ctrl-T to autocorrect.
editor.status.reserved_words = "color" and "int" are reserved words & cannot be used as variable names
editor.status.undefined_method = The function "%s(%s)" does not exist
editor.status.undefined_constructor = The constructor "%s(%s)" does not exist
Expand All @@ -369,6 +370,7 @@ editor.status.undef_global_var = The global variable "%s" does not exist
editor.status.undef_class = The class "%s" does not exist
editor.status.undef_var = The variable "%s" does not exist
editor.status.undef_name = The name "%s" cannot be recognized
editor.status.unterm_string_curly = String literal is not closed by a straight double quote. Curly quotes like %s won't help.
editor.status.type_mismatch = Type mismatch, "%s" does not match with "%s"
editor.status.unused_variable = The value of the local variable "%s" is not used
editor.status.uninitialized_variable = The local variable "%s" may not have been initialized
Expand Down
43 changes: 33 additions & 10 deletions java/src/processing/mode/java/AutoFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -639,25 +639,48 @@ public String format(final String source) {
break;

case '"':
case '“':
case '”':
case '\'':
case '‘':
case '’':
inStatementFlag = true;
buf.append(c);
char realQuote = c;
if (c == '“' || c == '”') realQuote = '"';
if (c == '‘' || c == '’') realQuote = '\'';
buf.append(realQuote);

char otherQuote = c;
if (c == '“') otherQuote = '”';
if (c == '”') otherQuote = '“';
if (c == '‘') otherQuote = '’';
if (c == '’') otherQuote = '‘';

char cc = nextChar();
while (!EOF && cc != c) {
// In a proper string, all the quotes tested are c. In a curly-quoted
// string, there are three possible end quotes: c, its reverse, and
// the correct straight quote.
while (!EOF && cc != otherQuote && cc != realQuote && cc != c) {
buf.append(cc);
if (cc == '\\') {
buf.append(cc = nextChar());
}
if (cc == '\n') {
writeIndentedLine();
startFlag = true;
}

// Syntax error: unterminated string. Leave \n in nextChar, so it
// feeds back into the loop.
if (peek() == '\n') break;
cc = nextChar();
}
buf.append(cc);
if (readForNewLine()) {
// push a newline into the stream
chars[pos--] = '\n';
if (cc == otherQuote || cc == realQuote || cc == c) {
buf.append(realQuote);
if (readForNewLine()) {
// push a newline into the stream
chars[pos--] = '\n';
}
} else {
// We've had a syntax error if the string wasn't terminated by EOL/
// EOF, just abandon this statement.
inStatementFlag = false;
}
break;

Expand Down
28 changes: 25 additions & 3 deletions java/src/processing/mode/java/JavaBuild.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.tools.ant.ProjectHelper;

import processing.app.Base;
import processing.app.Language;
import processing.app.Library;
import processing.app.Messages;
import processing.app.Mode;
Expand Down Expand Up @@ -345,9 +346,30 @@ public String preprocess(File srcFolder,

// System.err.println("and then she tells me " + tsre.toString());
// TODO not tested since removing ORO matcher.. ^ could be a problem
String mess = "^line (\\d+):(\\d+):\\s";
String locationRegex = "^line (\\d+):(\\d+):\\s";
String message = tsre.getMessage();
String[] m;

if (null != (m = PApplet.match(tsre.toString(),
"unexpected char: (.*)"))) {
char c = 0;
if (m[1].startsWith("0x")) { // Hex
c = (char) PApplet.unhex(m[1].substring(2));
} else if (m[1].length() == 3) { // Quoted
c = m[1].charAt(1);
} else if (m[1].length() == 1) { // Alone
c = m[1].charAt(0);
}
if (c == '\u201C' || c == '\u201D' || // “”
c == '\u2018' || c == '\u2019') { // ‘’
message = Language.interpolate("editor.status.bad_curly_quote", c);
} else if (c != 0) {
message = "Not expecting symbol " + m[1] +
", which is " + Character.getName(c) + ".";
}
}

String[] matches = PApplet.match(tsre.toString(), mess);
String[] matches = PApplet.match(tsre.toString(), locationRegex);
if (matches != null) {
int errorLine = Integer.parseInt(matches[1]) - 1;
int errorColumn = Integer.parseInt(matches[2]);
Expand All @@ -362,7 +384,7 @@ public String preprocess(File srcFolder,
}
errorLine -= sketch.getCode(errorFile).getPreprocOffset();

throw new SketchException(tsre.getMessage(),
throw new SketchException(message,
errorFile, errorLine, errorColumn);

} else {
Expand Down
64 changes: 51 additions & 13 deletions java/src/processing/mode/java/pdex/ErrorMessageSimplifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static String getIDName(int id) {
/**
* Tones down the jargon in the ecj reported errors.
*/
public static String getSimplifiedErrorMessage(IProblem iprob) {
public static String getSimplifiedErrorMessage(IProblem iprob, String badCode) {
if (iprob == null) return null;

String args[] = iprob.getArguments();
Expand All @@ -97,6 +97,7 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {
for (String arg : args) {
Messages.log("Arg " + arg);
}
Messages.log("Bad code: " + badCode);
}

String result = null;
Expand All @@ -111,6 +112,15 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {

case IProblem.ParsingErrorDeleteToken:
if (args.length > 0) {
if (args[0].equalsIgnoreCase("Invalid Character")) {
result = getErrorMessageForCurlyQuote(badCode);
}
}
break;

case IProblem.ParsingErrorDeleteTokens:
result = getErrorMessageForCurlyQuote(badCode);
if (result == null) {
result = Language.interpolate("editor.status.error_on", args[0]);
}
break;
Expand All @@ -136,13 +146,16 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {

case IProblem.ParsingErrorInvalidToken:
if (args.length > 0) {
if (args[1].equals("VariableDeclaratorId")) {
if (args[0].equals("int")) {
if (args[0].equals("int")) {
if (args[1].equals("VariableDeclaratorId")) {
result = Language.text("editor.status.reserved_words");
} else {
result = Language.interpolate("editor.status.error_on", args[0]);
}
} else {
} else if (args[0].equalsIgnoreCase("Invalid Character")) {
result = getErrorMessageForCurlyQuote(badCode);
}
if (result == null) {
result = Language.interpolate("editor.status.error_on", args[0]);
}
}
Expand All @@ -165,6 +178,9 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {
}
break;

case IProblem.ParsingErrorReplaceTokens:
result = getErrorMessageForCurlyQuote(badCode);

case IProblem.UndefinedConstructor:
if (args.length == 2) {
String constructorName = args[0];
Expand Down Expand Up @@ -230,6 +246,13 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {
}
break;

case IProblem.UnterminatedString:
if (badCode.contains("“") || badCode.contains("”")) {
result = Language.interpolate("editor.status.unterm_string_curly",
badCode.replaceAll("[^“”]", ""));
}
break;

case IProblem.TypeMismatch:
if (args.length > 1) {
result = Language.interpolate("editor.status.type_mismatch", args[0], args[1]);
Expand Down Expand Up @@ -261,16 +284,17 @@ public static String getSimplifiedErrorMessage(IProblem iprob) {
result = Language.interpolate("editor.status.hiding_enclosing_type", args[0]);
}
break;
}

default:
String message = iprob.getMessage();
if (message != null) {
// Remove all instances of token
// "Syntax error on token 'blah', delete this token"
Matcher matcher = tokenRegExp.matcher(message);
message = matcher.replaceAll("");
result = message;
}
if (result == null) {
String message = iprob.getMessage();
if (message != null) {
// Remove all instances of token
// "Syntax error on token 'blah', delete this token"
Matcher matcher = tokenRegExp.matcher(message);
message = matcher.replaceAll("");
result = message;
}
}

if (DEBUG) {
Expand Down Expand Up @@ -323,6 +347,20 @@ static private String getErrorMessageForBracket(char c) {
}


/**
* @param badCode The code which may contain curly quotes
* @return Friendly error message if there is a curly quote in badCode,
* null otherwise.
*/
static private String getErrorMessageForCurlyQuote(String badCode) {
if (badCode.contains("‘") || badCode.contains("’") ||
badCode.contains("“") || badCode.contains("”")) {
return Language.interpolate("editor.status.bad_curly_quote",
badCode.replaceAll("[^‘’“”]", ""));
} else return null;
}


// static private final String q(Object quotable) {
// return "\"" + quotable + "\"";
// }
Expand Down
6 changes: 4 additions & 2 deletions java/src/processing/mode/java/pdex/JavaProblem.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,17 @@ public JavaProblem(String message, int type, int tabIndex, int lineNumber) {
* @param iProblem - The IProblem which is being wrapped
* @param tabIndex - The tab number to which the error belongs to
* @param lineNumber - Line number(pde code) of the error
* @param badCode - The code iProblem refers to.
*/
public static JavaProblem fromIProblem(IProblem iProblem, int tabIndex, int lineNumber) {
public static JavaProblem fromIProblem(IProblem iProblem,
int tabIndex, int lineNumber, String badCode) {
int type = 0;
if(iProblem.isError()) {
type = ERROR;
} else if (iProblem.isWarning()) {
type = WARNING;
}
String message = ErrorMessageSimplifier.getSimplifiedErrorMessage(iProblem);
String message = ErrorMessageSimplifier.getSimplifiedErrorMessage(iProblem, badCode);
return new JavaProblem(message, type, tabIndex, lineNumber);
}

Expand Down
Loading