+ * Create a new issue emitter when access to the processing sketch source is not available.
+ * Note that this will not allow some error beautification and, if sketch source is available,
+ * use other constructor.
+ *
+ *
+ * @param newListener The listener to inform when encountering a syntax error.
+ */
+ public PdeIssueEmitter(PdePreprocessIssueListener newListener) {
+ listener = newListener;
+ sourceMaybe = Optional.empty();
+ }
+
+ /**
+ * Create a new issue emitter.
+ *
+ * @param newListener The listener to inform when encountering a syntax error.
+ * @param newSourceEmitter The sketch source to use when helping beautify certain syntax error
+ * messages.
+ */
+ public PdeIssueEmitter(PdePreprocessIssueListener newListener, SourceEmitter newSourceEmitter) {
+ listener = newListener;
+ sourceMaybe = Optional.of(newSourceEmitter);
+ }
+
+ @Override
+ public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line,
+ int charPositionInLine, String msg, RecognitionException e) {
+
+ PreprocessIssueMessageSimplifier facade = PreprocessIssueMessageSimplifier.get();
+ IssueMessageSimplification simplification = facade.simplify(msg);
+
+ IssueLocation issueLocation;
+
+ if (sourceMaybe.isPresent()) {
+ issueLocation = IssueLocationFactory.getLineWithOffset(
+ simplification,
+ line,
+ charPositionInLine,
+ sourceMaybe.get().getSource()
+ );
+ } else {
+ issueLocation = new IssueLocation(line, charPositionInLine);
+ }
+
+ listener.onIssue(new PdePreprocessIssue(
+ issueLocation.getLine(),
+ issueLocation.getCharPosition(),
+ simplification.getMessage()
+ ));
+ }
+
+ /**
+ * Simple interface for strategy which can emit the full body of a processing sketch.
+ */
+ public static interface SourceEmitter {
+
+ /**
+ * Get the full body of the processing sketch.
+ *
+ * @return String processing sketch source code across all tabs.
+ */
+ String getSource();
+
+ }
+
+ /**
+ * Interface for listener that responds to issues reported by the preprocessor.
+ */
+ public static interface PdePreprocessIssueListener {
+
+ /**
+ * Callback to invoke when an issue is encountered in preprocesing.
+ *
+ * @param issue Description of the issue.
+ */
+ void onIssue(PdePreprocessIssue issue);
+
+ }
+
+ /**
+ * ================================
+ * == Supporting data structures ==
+ * ================================
+ */
+
+ /**
+ * Data structure describing an issue simplification or explanation.
+ *
+ *
+ * Data structure describing an edit that was made to an error message or warning to be shown to
+ * the user based on a series of rules that attempts to make error messages easier to understand
+ * for the user.
+ *
+ */
+ public static class IssueMessageSimplification {
+
+ private final String message;
+ private final boolean attributeToPriorToken;
+
+ /**
+ * Create a new issue message simplification.
+ *
+ *
+ * Create a new issue message simplification that leaves the token attribution alone (the token
+ * on which the error was reported will be the same before error message simplification).
+ *
+ *
+ * @param newMessage The message to show to the user.
+ */
+ public IssueMessageSimplification(String newMessage) {
+ message = newMessage;
+ attributeToPriorToken = false;
+ }
+
+ /**
+ * Create a new issue message simplification.
+ *
+ *
+ * Create a new issue message simplification. Note that there is an option to have the error
+ * attributed to the "prior token". This is helpful, for example, when a semicolon is missing.
+ * The error is generated on the token after the line on which the semicolon was omitted so,
+ * while the error technically emerges on the next line, it is better for the user for it to
+ * appear earlier. Specifically, it is most sensible for it to appear on the "prior token".
+ *
+ *
+ * @param newMessage The message to show to the user.
+ * @param newAttributeToPriorToken Boolean flag indicating if the error should be shown on the
+ * token prior to the one on which the error was originally generated. True if the error should
+ * be attributed to the prior token. False otherwise.
+ */
+ public IssueMessageSimplification(String newMessage, boolean newAttributeToPriorToken) {
+ message = newMessage;
+ attributeToPriorToken = newAttributeToPriorToken;
+ }
+
+ /**
+ * Get the error message text that should be shown to the user.
+ *
+ * @return The error message text that should be shown to the user.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Flag indicating if the error should be attributed to the prior token.
+ *
+ * @return True if the error should be attributed to the prior non-skip token (not whitepsace or
+ * comment). This is useful when a mistake on a prior line like omitted semicolon causes an
+ * error on a later line but one wants error highlighting closer to the mistake itself. False
+ * if the error should be attributed to the original offending token.
+ */
+ public boolean getAttributeToPriorToken() {
+ return attributeToPriorToken;
+ }
+
+ }
+
+ /**
+ * Data structure describing where an issue occurred.
+ */
+ public static class IssueLocation {
+
+ private final int line;
+ private final int charPosition;
+
+ /**
+ * Create a new issue location structure.
+ *
+ * @param newLine The line (1-indexed) where the issue occurred. This should be in the global file
+ * generated by the preprocessor and not relative to the start of the tab.
+ * @param newCharPosition The position on the line.
+ */
+ public IssueLocation(int newLine, int newCharPosition) {
+ line = newLine;
+ charPosition = newCharPosition;
+ }
+
+ /**
+ * Get the 1-indexed line on which this error occurred.
+ *
+ * @return The line on which this error occurred. Note that this will be relative to the global
+ * file generated by the preprocessor and not relative to the start of the tab.
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * The the position of the error within the line.
+ *
+ * @return The number of characters including whitespace from the start of the line at which the
+ * error occurred.
+ */
+ public int getCharPosition() {
+ return charPosition;
+ }
+
+ }
+
+ /**
+ * =====================
+ * == Utility classes ==
+ * =====================
+ */
+
+ /**
+ * Utility that can help clean up where in source an issue should be reported.
+ *
+ *
+ * For some errors, the location of the "mistake" does not appear close to where the actual error
+ * is generated. For example, consider omitting a semicolon. Though the "mistake" is arguably on
+ * the line on which a semicolon is forgotten, the grammatical error appears in the first
+ * non-skip token after the omitted character. This means that the issue shown to the user may
+ * be far away from the line they would want to edit. This utility helps determine if an issue
+ * requires a new location and, if so, where the location should be.
+ *
+ */
+ public static class IssueLocationFactory {
+
+ /**
+ * Determine where an issue should be reported.
+ *
+ * @param simplification The issue simplification generated from {PreprocessIssueMessageSimplifier}.
+ * @param originalLine The original line (1 indexed) on which the issue was reported.
+ * @param originalOffset The original number of characters from the start of the line where the
+ * the issue was reported.
+ * @param source The full concatenated source of the sketch being built.
+ * @param lineCount The total
+ * @return The new location where the issue should be reported. This may be identical to the
+ * original location if the issue was not moved.
+ */
+ public static IssueLocation getLineWithOffset(IssueMessageSimplification simplification,
+ int originalLine, int originalOffset, String source) {
+
+ // Determine if the issue should be relocated
+ boolean shouldAttributeToPrior = simplification.getAttributeToPriorToken();
+ shouldAttributeToPrior = shouldAttributeToPrior && originalLine != 0;
+
+ if (!shouldAttributeToPrior) {
+ return new IssueLocation(originalLine, originalOffset);
+ }
+
+ // Find the code prior the issue
+ String priorCode = getContentsUpToLine(source, originalLine);
+
+ // Find the token immediately prior to the issue
+ PreprocessIssueMessageSimplifier.PriorTokenFinder finder = new PreprocessIssueMessageSimplifier.PriorTokenFinder();
+ int charPos = priorCode.length();
+ while (!finder.isDone() && charPos > 0) {
+ charPos--;
+ finder.step(priorCode.charAt(charPos));
+ }
+
+ // Find the location offset depending on if the prior token could be found
+ Optional foundStartOfMatchMaybe = finder.getTokenPositionMaybe();
+ int startOfMatch;
+ int linesOffset;
+
+ if (foundStartOfMatchMaybe.isPresent()) {
+ startOfMatch = priorCode.length() - foundStartOfMatchMaybe.get();
+ String contentsOfMatch = priorCode.substring(startOfMatch);
+ linesOffset = SourceUtil.getCount(contentsOfMatch, "\n");
+ } else {
+ startOfMatch = priorCode.length();
+ linesOffset = 0;
+ }
+
+ // Apply the location offset and highlight to the end of the line
+ String contentsPriorToMatch = priorCode.substring(0, startOfMatch);
+ int newLine = originalLine - linesOffset;
+ int lengthIncludingLine = contentsPriorToMatch.length();
+ int lengthExcludingLine = contentsPriorToMatch.lastIndexOf('\n');
+ int lineLength = lengthIncludingLine - lengthExcludingLine;
+ int col = lineLength - 1; // highlight from start of line to end
+
+ // Build the new issue location
+ return new IssueLocation(newLine, col);
+ }
+
+ /**
+ * Get all of the contents of source leading up to a line.
+ *
+ * @param source The full concatenated sketch source.
+ * @param endLineExclusive The line up to which code should be returned. Note that this is an
+ * "exclusive" boundary. Code from this line itself will not be included.
+ * @return All of the sketch code leading up to but not including the line given.
+ */
+ private static String getContentsUpToLine(String source, int endLineExclusive) {
+ int line = 0;
+ int stringCursor = 0;
+ int strLength = source.length();
+
+ while (line < endLineExclusive-1 && stringCursor < strLength) {
+ if (source.charAt(stringCursor) == '\n') {
+ line++;
+ }
+
+ stringCursor++;
+ }
+
+ return source.substring(0, stringCursor);
+ }
+
+ }
+
+}
diff --git a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java
index 74abacb3bf..00bca75b73 100644
--- a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java
+++ b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java
@@ -35,8 +35,6 @@
import processing.mode.java.SourceUtil;
import processing.mode.java.TextTransform;
import processing.mode.java.preproc.PdePreprocessor.Mode;
-import processing.mode.java.preproc.issue.PdePreprocessIssue;
-import processing.mode.java.preproc.issue.PreprocessIssueMessageSimplifier;
/**
* ANTLR tree traversal listener that preforms code rewrites as part of sketch preprocessing.
diff --git a/java/src/processing/mode/java/preproc/PdePreprocessIssue.java b/java/src/processing/mode/java/preproc/PdePreprocessIssue.java
new file mode 100644
index 0000000000..77df2a6f26
--- /dev/null
+++ b/java/src/processing/mode/java/preproc/PdePreprocessIssue.java
@@ -0,0 +1,52 @@
+package processing.mode.java.preproc;
+
+/**
+ * Issue emitted from the preprocessor.
+ */
+public class PdePreprocessIssue {
+
+ private final int line;
+ private final int charPositionInLine;
+ private final String msg;
+
+ /**
+ * Create a new record of an issue emitted from the preprocessor.
+ *
+ * @param newLine The line in the generated java file.
+ * @param newCharPositionInLine The character position in the source line.
+ * @param newMsg Description of the issue.
+ */
+ public PdePreprocessIssue(int newLine, int newCharPositionInLine, String newMsg) {
+ line = newLine;
+ charPositionInLine = newCharPositionInLine;
+ msg = newMsg;
+ }
+
+ /**
+ * Get the unified source line where the issue was found.
+ *
+ * @return The line in the output java source where the issue was found.
+ */
+ public int getLine() {
+ return line;
+ }
+
+ /**
+ * Get the character position in the source line of the issue.
+ *
+ * @return The source column where the issue was found.
+ */
+ public int getCharPositionInLine() {
+ return charPositionInLine;
+ }
+
+ /**
+ * Get a description of the issue found.
+ *
+ * @return Human-readable localized message describing the issue.
+ */
+ public String getMsg() {
+ return msg;
+ }
+
+}
diff --git a/java/src/processing/mode/java/preproc/PdePreprocessIssueException.java b/java/src/processing/mode/java/preproc/PdePreprocessIssueException.java
new file mode 100644
index 0000000000..8264ecf5bd
--- /dev/null
+++ b/java/src/processing/mode/java/preproc/PdePreprocessIssueException.java
@@ -0,0 +1,32 @@
+package processing.mode.java.preproc;
+
+
+import processing.mode.java.preproc.PdePreprocessIssue;
+
+/**
+ * Exception indicating that a preprocessor issue was found.
+ */
+public class PdePreprocessIssueException extends RuntimeException {
+
+ private final PdePreprocessIssue preprocessIssue;
+
+ /**
+ * Create a new exception indicating that there was a preprocessing issue.
+ *
+ * @param newPreprocessIssue Issue encountered.
+ */
+ public PdePreprocessIssueException(PdePreprocessIssue newPreprocessIssue) {
+ super(newPreprocessIssue.getMsg());
+ preprocessIssue = newPreprocessIssue;
+ }
+
+ /**
+ * Get information about the preprocessing issue found.
+ *
+ * @return Record of the preprocessor issue.
+ */
+ public PdePreprocessIssue getIssue() {
+ return preprocessIssue;
+ }
+
+}
diff --git a/java/src/processing/mode/java/preproc/PdePreprocessor.java b/java/src/processing/mode/java/preproc/PdePreprocessor.java
index 6b2b4c5263..b7961cef49 100644
--- a/java/src/processing/mode/java/preproc/PdePreprocessor.java
+++ b/java/src/processing/mode/java/preproc/PdePreprocessor.java
@@ -34,8 +34,6 @@
import processing.app.Preferences;
import processing.app.SketchException;
-import processing.mode.java.preproc.issue.PdeIssueEmitter;
-import processing.mode.java.preproc.issue.PdePreprocessIssue;
/**
diff --git a/java/src/processing/mode/java/preproc/issue/PreprocessIssueMessageSimplifier.java b/java/src/processing/mode/java/preproc/PreprocessIssueMessageSimplifier.java
similarity index 57%
rename from java/src/processing/mode/java/preproc/issue/PreprocessIssueMessageSimplifier.java
rename to java/src/processing/mode/java/preproc/PreprocessIssueMessageSimplifier.java
index 762dcadf31..39ab6d6ffc 100644
--- a/java/src/processing/mode/java/preproc/issue/PreprocessIssueMessageSimplifier.java
+++ b/java/src/processing/mode/java/preproc/PreprocessIssueMessageSimplifier.java
@@ -19,28 +19,26 @@
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import processing.app.Language;
import processing.app.Platform;
import processing.mode.java.SourceUtil;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
- * Facade that tries to create a better error message for syntax issues in input source.
+ * Utility class that generates localized error messages for incorrect sketch syntax.
*
*
- * Facade that interprets error messages from ANTLR in an attempt to generate an improved error
+ * Utility that interprets error messages from ANTLR in an attempt to generate an improved error
* message when describing grammatically incorrect input. This is distinct from compiler errors
- * caused after generating an AST.
+ * caused after generating an AST. This is required to produce the localized error messages.
*
*
*
@@ -100,19 +98,21 @@ public static String getLocalStr(String stringName) {
* @param originalMessage Error message generated from ANTLR.
* @return An improved error message or the originalMessage if no improvements could be made.
*/
- public IssueMessageSimplification simplify(String originalMessage) {
- Optional matching = strategies.stream()
+ public PdeIssueEmitter.IssueMessageSimplification simplify(String originalMessage) {
+ Optional matching = strategies.stream()
.map((x) -> x.simplify(originalMessage))
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
- return matching.orElse(new IssueMessageSimplification(originalMessage));
+ return matching.orElse(new PdeIssueEmitter.IssueMessageSimplification(originalMessage));
}
/* ============================
* === Enumerate strategies ===
* ============================
+ *
+ *
*/
/**
@@ -216,7 +216,7 @@ protected interface PreprocIssueMessageSimplifierStrategy {
* @return An optional with an improved message or an empty optional if no improvements could be
* made by this strategy.
*/
- Optional simplify(String message);
+ Optional simplify(String message);
}
@@ -266,7 +266,7 @@ protected EvenCountTemplateMessageSimplifierStrategy(String newToken, String new
}
@Override
- public Optional simplify(String message) {
+ public Optional simplify(String message) {
String messageContent = getOffendingArea(message);
if (filter.isPresent()) {
@@ -283,7 +283,7 @@ public Optional simplify(String message) {
token
);
return Optional.of(
- new IssueMessageSimplification(newMessage)
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage)
);
}
}
@@ -339,7 +339,7 @@ public TokenPairTemplateMessageSimplifierStrategy(String newToken1, String newTo
}
@Override
- public Optional simplify(String message) {
+ public Optional simplify(String message) {
String messageContent = getOffendingArea(message);
int count1 = SourceUtil.getCount(messageContent, token1);
@@ -361,7 +361,7 @@ public Optional simplify(String message) {
.replace("%c", "%s"), missingToken);
return Optional.of(
- new IssueMessageSimplification(newMessage)
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage)
);
}
@@ -420,7 +420,7 @@ public RegexTemplateMessageSimplifierStrategy(String newRegex, String newHintTem
}
@Override
- public Optional simplify(String message) {
+ public Optional simplify(String message) {
if (pattern.matcher(message).find()) {
String newMessage = String.format(
hintTemplate,
@@ -428,7 +428,7 @@ public Optional simplify(String message) {
);
return Optional.of(
- new IssueMessageSimplification(newMessage, getAttributeToPrior())
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage, getAttributeToPrior())
);
} else {
return Optional.empty();
@@ -553,7 +553,7 @@ protected PreprocIssueMessageSimplifierStrategy createMissingCurlyAtStartSimplif
return Optional.empty();
}
- return Optional.of(new IssueMessageSimplification(
+ return Optional.of(new PdeIssueEmitter.IssueMessageSimplification(
getLocalStr("editor.status.missing.left_curly_bracket")
));
};
@@ -568,7 +568,7 @@ protected PreprocIssueMessageSimplifierStrategy createMissingCurlyAtSemicolonSim
return Optional.empty();
}
- return Optional.of(new IssueMessageSimplification(
+ return Optional.of(new PdeIssueEmitter.IssueMessageSimplification(
getLocalStr("editor.status.missing.right_curly_bracket")
));
};
@@ -585,7 +585,7 @@ protected PreprocIssueMessageSimplifierStrategy createMissingIdentifierSimplifie
message.replace("missing Identifier at", "")
);
return Optional.of(
- new IssueMessageSimplification(newMessage)
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage)
);
} else {
return Optional.empty();
@@ -613,7 +613,7 @@ protected PreprocIssueMessageSimplifierStrategy createKnownMissingSimplifierStra
String newMessage = String.format(langTemplate, missingPiece);
- return Optional.of(new IssueMessageSimplification(newMessage));
+ return Optional.of(new PdeIssueEmitter.IssueMessageSimplification(newMessage));
} else {
return Optional.empty();
}
@@ -632,7 +632,7 @@ protected PreprocIssueMessageSimplifierStrategy createExtraneousInputSimplifierS
String newMessage = String.format(newMessageOuter, innerMsg);
return Optional.of(
- new IssueMessageSimplification(newMessage)
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage)
);
} else {
return Optional.empty();
@@ -655,7 +655,7 @@ protected PreprocIssueMessageSimplifierStrategy createMismatchedInputSimplifierS
);
return Optional.of(
- new IssueMessageSimplification(
+ new PdeIssueEmitter.IssueMessageSimplification(
newMessage
)
);
@@ -671,21 +671,382 @@ protected PreprocIssueMessageSimplifierStrategy createMismatchedInputSimplifierS
protected static class DefaultMessageSimplifier implements PreprocIssueMessageSimplifierStrategy {
@Override
- public Optional simplify(String message) {
+ public Optional simplify(String message) {
if (message.contains("viable alternative")) {
String newMessage = String.format(
getLocalizedGenericError("%s"),
getOffendingArea(message)
);
return Optional.of(
- new IssueMessageSimplification(newMessage)
+ new PdeIssueEmitter.IssueMessageSimplification(newMessage)
);
} else {
return Optional.of(
- new IssueMessageSimplification(message)
+ new PdeIssueEmitter.IssueMessageSimplification(message)
);
}
}
}
+ /**
+ * =====================
+ * == Utility classes ==
+ * =====================
+ */
+
+ /**
+ * Simple automaton that reads backwards from a position in source to find the prior token.
+ *
+ *
+ * When helping generate messages for the user, it is often useful to be able to locate the
+ * position of the first token immediately before another location in source. For example,
+ * consider error reporting when a semicolon is missing. The error is generated on the token after
+ * the line on which the semicolon was omitted so, while the error technically emerges on the next
+ * line, it is better for the user for it to appear earlier. Specifically, it is most sensible for
+ * it to appear on the "prior token" because this is where it was forgotten.
+ *
+ *
+ *
+ * To that end, this finite state automaton can read backwards from a position in source to locate
+ * the first "non-skip token" preceding that location. Here a "skip" token means one that is
+ * ignored by the preprocessor and does not impact output code (this includes comments and
+ * whitespace). This automaton will read character by character from source until it knows it has
+ * seen a non-skip token, returning the location of that non-skip token.
+ *
+ *
+ *
+ * A formalized FSA is useful here in order to traverse code which can have a complex grammar.
+ * As there are a number of ways in the Java / Processing grammar one can encounter skip tokens,
+ * this formalized implementation describes the state machine directly in order to provide
+ * hopefully more readability / transparency compared to a regex without requiring the use of
+ * something heavier like ANTLR.
+ *
+ */
+ public static class PriorTokenFinder {
+
+ // Simple regex matching all "whitespace" characters recognized by the ANTLR grammar.
+ private static final String WS_PATTERN = "[ \\t\\r\\n\\u000C]";
+
+ // Possible states for this FSA
+ private enum AutomatonState {
+
+ // Automaton is not certain if it is parsing a skip or non-skip character
+ UNKNOWN,
+
+ // Automaton has found a possible token but it is not sure if inside a comment
+ POSSIBLE_TOKEN,
+
+ // Automaton has found a token but also a forward slash so, if the next character is also a "/",
+ // it is inside a single line comment.
+ TOKEN_OR_MAYBE_SL_COMMENT,
+
+ // Automaton has found a forward slash so, depending on the next character, it may be inside a
+ // single line comment, multi-line comment, or it may have found a standalone token.
+ TOKEN_OR_MAYBE_COMMENT,
+
+ // Automaton has found a token and hit its terminal state.
+ TOKEN,
+
+ // Automaton is current traversing a multi-line comment.
+ MULTI_LINE_COMMENT,
+
+ // Automaton is maybe leaving a multi line comment because it found an "*". If it picks up a "/"
+ // next, the automaton knows it is no longer within a multi-line comment.
+ MAYBE_LEAVE_MULTI_LINE_COMMENT
+ }
+
+ private boolean done;
+ private Optional tokenPosition;
+ private AutomatonState state;
+ private int charPosition;
+ private Pattern whitespacePattern;
+
+ /**
+ * Create a new automaton in unknown state and a character position of zero.
+ */
+ PriorTokenFinder() {
+ whitespacePattern = Pattern.compile(WS_PATTERN);
+ reset();
+ }
+
+ /**
+ * Determine if this automaton has found a token.
+ *
+ * @return True if this automaton has found a token and, thus, is in terminal state (so will
+ * ignore all future input). False if this autoamton has not yet found a token since creation
+ * or last call to reset.
+ */
+ boolean isDone() {
+ return done;
+ }
+
+ /**
+ * Get the position of the token found.
+ *
+ * @return Optional containing the number of characters processed prior to finding the token or
+ * empty if no token found. Note that this is different the number of total characters
+ * processed as some extra characters have to be read prior to the token itself to ensure it is
+ * not part of a comment or something similar.
+ */
+ Optional getTokenPositionMaybe() {
+ return tokenPosition;
+ }
+
+ /**
+ * Reset this automaton to UNKNOWN state with a character count of zero.
+ */
+ void reset() {
+ done = false;
+ tokenPosition = Optional.empty();
+ state = AutomatonState.UNKNOWN;
+ charPosition = 0;
+ }
+
+ /**
+ * Process a character.
+ *
+ *
+ * Process the next character in an effort to find the "prior token". Note that this is
+ * expecting the processing sketch source code to be fed one character at a time
+ * backwards from the starting position in code. This is because it is looking for the
+ * first non-skip token immediately preceding a position in source.
+ *
+ *
+ * @param input The next character to process.
+ */
+ void step(char input) {
+ switch(state) {
+ case UNKNOWN: stepUnknown(input); break;
+ case POSSIBLE_TOKEN: stepPossibleToken(input); break;
+ case TOKEN_OR_MAYBE_SL_COMMENT: stepTokenOrMaybeSingleLineComment(input); break;
+ case TOKEN_OR_MAYBE_COMMENT: stepTokenOrMaybeComment(input); break;
+ case MULTI_LINE_COMMENT: stepMultiLineComment(input); break;
+ case MAYBE_LEAVE_MULTI_LINE_COMMENT: stepMaybeLeaveMultiLineComment(input); break;
+ case TOKEN: /* Already have token. Nothing to be done. */ break;
+ }
+
+ charPosition++;
+ }
+
+ /**
+ * Process the next character while in the UNKNOWN state.
+ *
+ *
+ * While not certain if looking at a skip or non-skip token, read the next character. If
+ * whitespace, can ignore. If a forward slash, could indicate either a comment or a possible
+ * token (move to TOKEN_OR_MAYBE_COMMENT). If anything else, may have found token but need to
+ * ensure this line isn't part of a comment (move to POSSIBLE_TOKEN).
+ *
+ *
+ * @param input The next character to process.
+ */
+ private void stepUnknown(char input) {
+ if (isWhitespace(input)) {
+ return;
+ }
+
+ tokenPosition = Optional.of(charPosition);
+
+ if (input == '/') {
+ state = AutomatonState.TOKEN_OR_MAYBE_COMMENT;
+ } else {
+ state = AutomatonState.POSSIBLE_TOKEN;
+ }
+ }
+
+ /**
+ * Process the next character while in the POSSIBLE_TOKEN state.
+ *
+ *
+ * After having found a character that could indicate a token, need to ensure that the token
+ * wasn't actually part of a single line comment ("//") so look for forward slashes (if found
+ * move to TOKEN_OR_MAYBE_SL_COMMENT). If encountered a newline, the earlier found token was
+ * not part of a comment so enter TOKEN state.
+ *
+ *
+ * @param input The next character to process.
+ */
+ private void stepPossibleToken(char input) {
+ if (input == '\n') {
+ enterNonSkipTokenState();
+ } else if (input == '/') {
+ state = AutomatonState.TOKEN_OR_MAYBE_SL_COMMENT;
+ }
+
+ // Else stay put
+ }
+
+ /**
+ * Process the next character while in the TOKEN_OR_MAYBE_SL_COMMENT state.
+ *
+ *
+ * After having found a forward slash after encountering something else which may be a non-skip
+ * token, one needs to check that it is preceded by another forward slash to have detected a
+ * single line comment (return to UNKNOWN state). If found a new line, that forward slash was
+ * actually a non-skip token itself so enter TOKEN state. Finally, if anything else, it is still
+ * possible that we are traversing a single line comment so return to POSSIBLE_TOKEN state.
+ *
+ *
+ * @param input The next character to process.
+ */
+ private void stepTokenOrMaybeSingleLineComment(char input) {
+ if (input == '\n') {
+ enterNonSkipTokenState();
+ } else if (input == '/') {
+ returnToUnknownState();
+ } else {
+ state = AutomatonState.POSSIBLE_TOKEN;
+ }
+ }
+
+ /**
+ * Process the next character while in the TOKEN_OR_MAYBE_COMMENT state.
+ *
+ *
+ * After having found a forward slash without encountering something else that may be a non-skip
+ * token: that forward slash is a non-skip token if preceded by a newline, could be a single
+ * line comment if preceded by a forward slash, could be a multi-line comment if preceded
+ * by an asterisk, or could by a non-skip token otherwise.
+ *
+ *
+ * @param input The next character to process.
+ */
+ private void stepTokenOrMaybeComment(char input) {
+ if (input == '\n') {
+ enterNonSkipTokenState();
+ } else if (input == '/') {
+ returnToUnknownState();
+ } else if (input == '*') {
+ enterMultilineComment();
+ } else {
+ state = AutomatonState.POSSIBLE_TOKEN;
+ }
+ }
+
+ /**
+ * Process the next character while in the MULTI_LINE_COMMENT state.
+ *
+ *
+ * Process the next character while traversing a multi-line comment. If an asterisk, we may be
+ * encountering the end of the multiline comment (move to MAYBE_LEAVE_MULTI_LINE_COMMENT).
+ * Otherwise, can ignore character.
+ *
+ *
+ * @param input The next character to process.
+ */
+ private void stepMultiLineComment(char input) {
+ if (input == '*') {
+ state = AutomatonState.MAYBE_LEAVE_MULTI_LINE_COMMENT;
+ }
+
+ // else stay put
+ }
+
+ /**
+ * Process the next character while in the MAYBE_LEAVE_MULTI_LINE_COMMENT state.
+ *
+ *
+ * If already found an asterisk while inside a multi-line comment, one may be leaving the multi-
+ * line comment depending on the next character. If forward slash, at end of comment (return to
+ * UNKNOWN state). If another asterisk, could still end comment depending on next character
+ * (stay in current state). Finally, if anything else, we are still in the body of the multi-
+ * line comment and not about to leave (return to MULTI_LINE_COMMENT state).
+ *
+ *
+ * @param input
+ */
+ private void stepMaybeLeaveMultiLineComment(char input) {
+ if (input == '/') {
+ state = AutomatonState.UNKNOWN;
+ } else if (input != '*') {
+ state = AutomatonState.MULTI_LINE_COMMENT;
+ }
+
+ // If * stay put
+ }
+
+ /**
+ * Convenience function to set up internal FSA state when entering a multi-line comment.
+ */
+ private void enterMultilineComment() {
+ tokenPosition = Optional.of(charPosition);
+ state = AutomatonState.MULTI_LINE_COMMENT;
+ }
+
+ /**
+ * Convenience function to set up internal FSA state when having found a non-skip token.
+ */
+ private void enterNonSkipTokenState() {
+ done = true;
+ state = AutomatonState.TOKEN;
+ }
+
+ /**
+ * Convenience function to set up internal FSA state when entering UNKNOWN state.
+ */
+ private void returnToUnknownState() {
+ tokenPosition = Optional.empty();
+ state = AutomatonState.UNKNOWN;
+ }
+
+ /**
+ * Convenience function which determines if a character is whitespace.
+ *
+ * @param input The character to test.
+ * @return True if whitespace. False otherwise.
+ */
+ private boolean isWhitespace(char input) {
+ return whitespacePattern.matcher("" + input).find();
+ }
+
+ }
+
+ /**
+ * Singleton with fallback error localizations.
+ */
+ public static class DefaultErrorLocalStrSet {
+
+ private static final AtomicReference instance = new AtomicReference<>();
+
+ private final Map localizations = new HashMap<>();
+
+ /**
+ * Get shared copy of this singleton.
+ *
+ * @return Shared singleton copy.
+ */
+ public static DefaultErrorLocalStrSet get() {
+ instance.compareAndSet(null, new DefaultErrorLocalStrSet());
+ return instance.get();
+ }
+
+ /**
+ * Private hidden constructor.
+ */
+ private DefaultErrorLocalStrSet() {
+ localizations.put("editor.status.error", "Error");
+ localizations.put("editor.status.error.syntax", "Syntax Error - %s");
+ localizations.put("editor.status.bad.assignment", "Error on variable assignment near %s?");
+ localizations.put("editor.status.bad.identifier", "Identifier cannot start with digits near %s?");
+ localizations.put("editor.status.bad.parameter", "Error on parameter or method declaration near %s?");
+ localizations.put("editor.status.extraneous", "Unexpected extra code near %s?");
+ localizations.put("editor.status.mismatched", "Missing operator or semicolon near %s?");
+ localizations.put("editor.status.missing.name", "Missing name near %s?");
+ localizations.put("editor.status.missing.type", "Missing name or type near %s?");
+ localizations.put("editor.status.missing.default", "Missing '%s'?");
+ localizations.put("editor.status.missing.right_curly_bracket", "Missing '}'");
+ localizations.put("editor.status.missing.left_curly_bracket", "Missing '{'");
+ }
+
+ /**
+ * Lookup localization.
+ *
+ * @param key Name of string.
+ * @return Value of string or empty if not given.
+ */
+ public Optional get(String key) {
+ return Optional.ofNullable(localizations.getOrDefault(key, null));
+ }
+
+ }
}
diff --git a/java/src/processing/mode/java/preproc/PreprocessorResult.java b/java/src/processing/mode/java/preproc/PreprocessorResult.java
index e8eff3d2bf..2c2d8b7295 100644
--- a/java/src/processing/mode/java/preproc/PreprocessorResult.java
+++ b/java/src/processing/mode/java/preproc/PreprocessorResult.java
@@ -27,7 +27,6 @@
import processing.mode.java.ImportStatement;
import processing.mode.java.TextTransform;
-import processing.mode.java.preproc.issue.PdePreprocessIssue;
/**
diff --git a/java/src/processing/mode/java/preproc/issue/DefaultErrorLocalStrSet.java b/java/src/processing/mode/java/preproc/issue/DefaultErrorLocalStrSet.java
deleted file mode 100644
index 54fe3686da..0000000000
--- a/java/src/processing/mode/java/preproc/issue/DefaultErrorLocalStrSet.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package processing.mode.java.preproc.issue;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Singleton with fallback error localizations.
- */
-public class DefaultErrorLocalStrSet {
-
- private static final AtomicReference instance = new AtomicReference<>();
-
- private final Map localizations = new HashMap<>();
-
- /**
- * Get shared copy of this singleton.
- *
- * @return Shared singleton copy.
- */
- public static DefaultErrorLocalStrSet get() {
- instance.compareAndSet(null, new DefaultErrorLocalStrSet());
- return instance.get();
- }
-
- /**
- * Private hidden constructor.
- */
- private DefaultErrorLocalStrSet() {
- localizations.put("editor.status.error", "Error");
- localizations.put("editor.status.error.syntax", "Syntax Error - %s");
- localizations.put("editor.status.bad.assignment", "Error on variable assignment near %s?");
- localizations.put("editor.status.bad.identifier", "Identifier cannot start with digits near %s?");
- localizations.put("editor.status.bad.parameter", "Error on parameter or method declaration near %s?");
- localizations.put("editor.status.extraneous", "Unexpected extra code near %s?");
- localizations.put("editor.status.mismatched", "Missing operator or semicolon near %s?");
- localizations.put("editor.status.missing.name", "Missing name near %s?");
- localizations.put("editor.status.missing.type", "Missing name or type near %s?");
- localizations.put("editor.status.missing.default", "Missing '%s'?");
- localizations.put("editor.status.missing.right_curly_bracket", "Missing '}'");
- localizations.put("editor.status.missing.left_curly_bracket", "Missing '{'");
- }
-
- /**
- * Lookup localization.
- *
- * @param key Name of string.
- * @return Value of string or empty if not given.
- */
- public Optional get(String key) {
- return Optional.ofNullable(localizations.getOrDefault(key, null));
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/IssueLocation.java b/java/src/processing/mode/java/preproc/issue/IssueLocation.java
deleted file mode 100644
index 7188e26df3..0000000000
--- a/java/src/processing/mode/java/preproc/issue/IssueLocation.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
-Part of the Processing project - http://processing.org
-
-Copyright (c) 2012-19 The Processing Foundation
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2
-as published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.mode.java.preproc.issue;
-
-
-/**
- * Data structure describing where an issue occurred.
- */
-public class IssueLocation {
-
- private final int line;
- private final int charPosition;
-
- /**
- * Create a new issue location structure.
- *
- * @param newLine The line (1-indexed) where the issue occurred. This should be in the global file
- * generated by the preprocessor and not relative to the start of the tab.
- * @param newCharPosition The position on the line.
- */
- public IssueLocation(int newLine, int newCharPosition) {
- line = newLine;
- charPosition = newCharPosition;
- }
-
- /**
- * Get the 1-indexed line on which this error occurred.
- *
- * @return The line on which this error occurred. Note that this will be relative to the global
- * file generated by the preprocessor and not relative to the start of the tab.
- */
- public int getLine() {
- return line;
- }
-
- /**
- * The the position of the error within the line.
- *
- * @return The number of characters including whitespace from the start of the line at which the
- * error occurred.
- */
- public int getCharPosition() {
- return charPosition;
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/IssueLocationFactory.java b/java/src/processing/mode/java/preproc/issue/IssueLocationFactory.java
deleted file mode 100644
index 9780d3e2c0..0000000000
--- a/java/src/processing/mode/java/preproc/issue/IssueLocationFactory.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
-Part of the Processing project - http://processing.org
-
-Copyright (c) 2012-19 The Processing Foundation
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2
-as published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.mode.java.preproc.issue;
-
-import java.util.Optional;
-
-import processing.mode.java.SourceUtil;
-
-
-/**
- * Utility that can help clean up where in source an issue should be reported.
- *
- *
- * For some errors, the location of the "mistake" does not appear close to where the actual error
- * is generated. For example, consider omitting a semicolon. Though the "mistake" is arguably on
- * the line on which a semicolon is forgotten, the grammatical error appears in the first
- * non-skip token after the omitted character. This means that the issue shown to the user may
- * be far away from the line they would want to edit. This utility helps determine if an issue
- * requires a new location and, if so, where the location should be.
- *
- */
-public class IssueLocationFactory {
-
- /**
- * Determine where an issue should be reported.
- *
- * @param simplification The issue simplification generated from {PreprocessIssueMessageSimplifier}.
- * @param originalLine The original line (1 indexed) on which the issue was reported.
- * @param originalOffset The original number of characters from the start of the line where the
- * the issue was reported.
- * @param source The full concatenated source of the sketch being built.
- * @param lineCount The total
- * @return The new location where the issue should be reported. This may be identical to the
- * original location if the issue was not moved.
- */
- public static IssueLocation getLineWithOffset(IssueMessageSimplification simplification,
- int originalLine, int originalOffset, String source) {
-
- // Determine if the issue should be relocated
- boolean shouldAttributeToPrior = simplification.getAttributeToPriorToken();
- shouldAttributeToPrior = shouldAttributeToPrior && originalLine != 0;
-
- if (!shouldAttributeToPrior) {
- return new IssueLocation(originalLine, originalOffset);
- }
-
- // Find the code prior the issue
- String priorCode = getContentsUpToLine(source, originalLine);
-
- // Find the token immediately prior to the issue
- PriorTokenFinder finder = new PriorTokenFinder();
- int charPos = priorCode.length();
- while (!finder.isDone() && charPos > 0) {
- charPos--;
- finder.step(priorCode.charAt(charPos));
- }
-
- // Find the location offset depending on if the prior token could be found
- Optional foundStartOfMatchMaybe = finder.getTokenPositionMaybe();
- int startOfMatch;
- int linesOffset;
-
- if (foundStartOfMatchMaybe.isPresent()) {
- startOfMatch = priorCode.length() - foundStartOfMatchMaybe.get();
- String contentsOfMatch = priorCode.substring(startOfMatch);
- linesOffset = SourceUtil.getCount(contentsOfMatch, "\n");
- } else {
- startOfMatch = priorCode.length();
- linesOffset = 0;
- }
-
- // Apply the location offset and highlight to the end of the line
- String contentsPriorToMatch = priorCode.substring(0, startOfMatch);
- int newLine = originalLine - linesOffset;
- int lengthIncludingLine = contentsPriorToMatch.length();
- int lengthExcludingLine = contentsPriorToMatch.lastIndexOf('\n');
- int lineLength = lengthIncludingLine - lengthExcludingLine;
- int col = lineLength - 1; // highlight from start of line to end
-
- // Build the new issue location
- return new IssueLocation(newLine, col);
- }
-
- /**
- * Get all of the contents of source leading up to a line.
- *
- * @param source The full concatenated sketch source.
- * @param endLineExclusive The line up to which code should be returned. Note that this is an
- * "exclusive" boundary. Code from this line itself will not be included.
- * @return All of the sketch code leading up to but not including the line given.
- */
- private static String getContentsUpToLine(String source, int endLineExclusive) {
- int line = 0;
- int stringCursor = 0;
- int strLength = source.length();
-
- while (line < endLineExclusive-1 && stringCursor < strLength) {
- if (source.charAt(stringCursor) == '\n') {
- line++;
- }
-
- stringCursor++;
- }
-
- return source.substring(0, stringCursor);
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/IssueMessageSimplification.java b/java/src/processing/mode/java/preproc/issue/IssueMessageSimplification.java
deleted file mode 100644
index eb8377584a..0000000000
--- a/java/src/processing/mode/java/preproc/issue/IssueMessageSimplification.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
-Part of the Processing project - http://processing.org
-
-Copyright (c) 2012-19 The Processing Foundation
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2
-as published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.mode.java.preproc.issue;
-
-
-/**
- * Data structure describing an issue simplification or explanation.
- *
- *
- * Data structure describing an edit that was made to an error message or warning to be shown to
- * the user based on a series of rules that attempts to make error messages easier to understand
- * for the user.
- *
- */
-public class IssueMessageSimplification {
-
- private final String message;
- private final boolean attributeToPriorToken;
-
- /**
- * Create a new issue message simplification.
- *
- *
- * Create a new issue message simplification that leaves the token attribution alone (the token
- * on which the error was reported will be the same before error message simplification).
- *
- *
- * @param newMessage The message to show to the user.
- */
- public IssueMessageSimplification(String newMessage) {
- message = newMessage;
- attributeToPriorToken = false;
- }
-
- /**
- * Create a new issue message simplification.
- *
- *
- * Create a new issue message simplification. Note that there is an option to have the error
- * attributed to the "prior token". This is helpful, for example, when a semicolon is missing.
- * The error is generated on the token after the line on which the semicolon was omitted so,
- * while the error technically emerges on the next line, it is better for the user for it to
- * appear earlier. Specifically, it is most sensible for it to appear on the "prior token".
- *
- *
- * @param newMessage The message to show to the user.
- * @param newAttributeToPriorToken Boolean flag indicating if the error should be shown on the
- * token prior to the one on which the error was originally generated. True if the error should
- * be attributed to the prior token. False otherwise.
- */
- public IssueMessageSimplification(String newMessage, boolean newAttributeToPriorToken) {
- message = newMessage;
- attributeToPriorToken = newAttributeToPriorToken;
- }
-
- /**
- * Get the error message text that should be shown to the user.
- *
- * @return The error message text that should be shown to the user.
- */
- public String getMessage() {
- return message;
- }
-
- /**
- * Flag indicating if the error should be attributed to the prior token.
- *
- * @return True if the error should be attributed to the prior non-skip token (not whitepsace or
- * comment). This is useful when a mistake on a prior line like omitted semicolon causes an
- * error on a later line but one wants error highlighting closer to the mistake itself. False
- * if the error should be attributed to the original offending token.
- */
- public boolean getAttributeToPriorToken() {
- return attributeToPriorToken;
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/PdeIssueEmitter.java b/java/src/processing/mode/java/preproc/issue/PdeIssueEmitter.java
deleted file mode 100644
index d7f3acc75b..0000000000
--- a/java/src/processing/mode/java/preproc/issue/PdeIssueEmitter.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
- Part of the Processing project - http://processing.org
-
- Copyright (c) 2019 The Processing Foundation
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2
- as published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.mode.java.preproc.issue;
-
-import org.antlr.v4.runtime.BaseErrorListener;
-import org.antlr.v4.runtime.RecognitionException;
-import org.antlr.v4.runtime.Recognizer;
-
-import java.util.Optional;
-
-
-/**
- * ANTLR error listener to inform a preprocess issue listener when syntax errors are encountered.
- *
- *
- * A {BaseErrorListener} which looks for syntax errors reported by ANTLR and converts them to
- * {PdePreprocessIssue}s that are consumable by a {PdePreprocessIssueListener}. It does this by
- * running the {PreprocessIssueMessageSimplifier} to generate a more user-friendly error message
- * before informing the provided listener.
- *
- */
-public class PdeIssueEmitter extends BaseErrorListener {
-
- private final PdePreprocessIssueListener listener;
- private final Optional sourceMaybe;
-
- /**
- * Create a new issue emitter.
- *
- *
- * Create a new issue emitter when access to the processing sketch source is not available.
- * Note that this will not allow some error beautification and, if sketch source is available,
- * use other constructor.
- *
- *
- * @param newListener The listener to inform when encountering a syntax error.
- */
- public PdeIssueEmitter(PdePreprocessIssueListener newListener) {
- listener = newListener;
- sourceMaybe = Optional.empty();
- }
-
- /**
- * Create a new issue emitter.
- *
- * @param newListener The listener to inform when encountering a syntax error.
- * @param newSourceEmitter The sketch source to use when helping beautify certain syntax error
- * messages.
- */
- public PdeIssueEmitter(PdePreprocessIssueListener newListener, SourceEmitter newSourceEmitter) {
- listener = newListener;
- sourceMaybe = Optional.of(newSourceEmitter);
- }
-
- @Override
- public void syntaxError(Recognizer, ?> recognizer, Object offendingSymbol, int line,
- int charPositionInLine, String msg, RecognitionException e) {
-
- PreprocessIssueMessageSimplifier facade = PreprocessIssueMessageSimplifier.get();
- IssueMessageSimplification simplification = facade.simplify(msg);
-
- IssueLocation issueLocation;
-
- if (sourceMaybe.isPresent()) {
- issueLocation = IssueLocationFactory.getLineWithOffset(
- simplification,
- line,
- charPositionInLine,
- sourceMaybe.get().getSource()
- );
- } else {
- issueLocation = new IssueLocation(line, charPositionInLine);
- }
-
- listener.onIssue(new PdePreprocessIssue(
- issueLocation.getLine(),
- issueLocation.getCharPosition(),
- simplification.getMessage()
- ));
- }
-
- /**
- * Simple interface for strategy which can emit the full body of a processing sketch.
- */
- public static interface SourceEmitter {
-
- /**
- * Get the full body of the processing sketch.
- *
- * @return String processing sketch source code across all tabs.
- */
- String getSource();
-
- }
-
- /**
- * Interface for listener that responds to issues reported by the preprocessor.
- */
- public static interface PdePreprocessIssueListener {
-
- /**
- * Callback to invoke when an issue is encountered in preprocesing.
- *
- * @param issue Description of the issue.
- */
- void onIssue(PdePreprocessIssue issue);
-
- }
-}
diff --git a/java/src/processing/mode/java/preproc/issue/PdePreprocessIssue.java b/java/src/processing/mode/java/preproc/issue/PdePreprocessIssue.java
deleted file mode 100644
index df40536035..0000000000
--- a/java/src/processing/mode/java/preproc/issue/PdePreprocessIssue.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package processing.mode.java.preproc.issue;
-
-public class PdePreprocessIssue {
-
- private final int line;
- private final int charPositionInLine;
- private final String msg;
-
- public PdePreprocessIssue(int newLine, int newCharPositionInLine, String newMsg) {
- line = newLine;
- charPositionInLine = newCharPositionInLine;
- msg = newMsg;
- }
-
- public int getLine() {
- return line;
- }
-
- public int getCharPositionInLine() {
- return charPositionInLine;
- }
-
- public String getMsg() {
- return msg;
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/PdePreprocessIssueException.java b/java/src/processing/mode/java/preproc/issue/PdePreprocessIssueException.java
deleted file mode 100644
index 72aeae9af2..0000000000
--- a/java/src/processing/mode/java/preproc/issue/PdePreprocessIssueException.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package processing.mode.java.preproc.issue;
-
-
-public class PdePreprocessIssueException extends RuntimeException {
-
- private final PdePreprocessIssue preprocessIssue;
-
- public PdePreprocessIssueException(PdePreprocessIssue newPreprocessIssue) {
- super(newPreprocessIssue.getMsg());
- preprocessIssue = newPreprocessIssue;
- }
-
- public PdePreprocessIssue getIssue() {
- return preprocessIssue;
- }
-
-}
diff --git a/java/src/processing/mode/java/preproc/issue/PriorTokenFinder.java b/java/src/processing/mode/java/preproc/issue/PriorTokenFinder.java
deleted file mode 100644
index 51e8106a81..0000000000
--- a/java/src/processing/mode/java/preproc/issue/PriorTokenFinder.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-
-/*
-Part of the Processing project - http://processing.org
-
-Copyright (c) 2012-19 The Processing Foundation
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License version 2
-as published by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software Foundation,
-Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-package processing.mode.java.preproc.issue;
-
-import java.util.Optional;
-import java.util.regex.Pattern;
-
-
-/**
- * Simple automaton that reads backwards from a position in source to find the prior token.
- *
- *
- * When helping generate messages for the user, it is often useful to be able to locate the
- * position of the first token immediately before another location in source. For example,
- * consider error reporting when a semicolon is missing. The error is generated on the token after
- * the line on which the semicolon was omitted so, while the error technically emerges on the next
- * line, it is better for the user for it to appear earlier. Specifically, it is most sensible for
- * it to appear on the "prior token" because this is where it was forgotten.
- *
- *
- *
- * To that end, this finite state automaton can read backwards from a position in source to locate
- * the first "non-skip token" preceding that location. Here a "skip" token means one that is
- * ignored by the preprocessor and does not impact output code (this includes comments and
- * whitespace). This automaton will read character by character from source until it knows it has
- * seen a non-skip token, returning the location of that non-skip token.
- *
- *
- *
- * A formalized FSA is useful here in order to traverse code which can have a complex grammar.
- * As there are a number of ways in the Java / Processing grammar one can encounter skip tokens,
- * this formalized implementation describes the state machine directly in order to provide
- * hopefully more readability / transparency compared to a regex without requiring the use of
- * something heavier like ANTLR.
- *
- */
-public class PriorTokenFinder {
-
- // Simple regex matching all "whitespace" characters recognized by the ANTLR grammar.
- private static final String WS_PATTERN = "[ \\t\\r\\n\\u000C]";
-
- // Possible states for this FSA
- private enum AutomatonState {
-
- // Automaton is not certain if it is parsing a skip or non-skip character
- UNKNOWN,
-
- // Automaton has found a possible token but it is not sure if inside a comment
- POSSIBLE_TOKEN,
-
- // Automaton has found a token but also a forward slash so, if the next character is also a "/",
- // it is inside a single line comment.
- TOKEN_OR_MAYBE_SL_COMMENT,
-
- // Automaton has found a forward slash so, depending on the next character, it may be inside a
- // single line comment, multi-line comment, or it may have found a standalone token.
- TOKEN_OR_MAYBE_COMMENT,
-
- // Automaton has found a token and hit its terminal state.
- TOKEN,
-
- // Automaton is current traversing a multi-line comment.
- MULTI_LINE_COMMENT,
-
- // Automaton is maybe leaving a multi line comment because it found an "*". If it picks up a "/"
- // next, the automaton knows it is no longer within a multi-line comment.
- MAYBE_LEAVE_MULTI_LINE_COMMENT
- }
-
- private boolean done;
- private Optional tokenPosition;
- private AutomatonState state;
- private int charPosition;
- private Pattern whitespacePattern;
-
- /**
- * Create a new automaton in unknown state and a character position of zero.
- */
- public PriorTokenFinder() {
- whitespacePattern = Pattern.compile(WS_PATTERN);
- reset();
- }
-
- /**
- * Determine if this automaton has found a token.
- *
- * @return True if this automaton has found a token and, thus, is in terminal state (so will
- * ignore all future input). False if this autoamton has not yet found a token since creation
- * or last call to reset.
- */
- public boolean isDone() {
- return done;
- }
-
- /**
- * Get the position of the token found.
- *
- * @return Optional containing the number of characters processed prior to finding the token or
- * empty if no token found. Note that this is different the number of total characters
- * processed as some extra characters have to be read prior to the token itself to ensure it is
- * not part of a comment or something similar.
- */
- public Optional getTokenPositionMaybe() {
- return tokenPosition;
- }
-
- /**
- * Reset this automaton to UNKNOWN state with a character count of zero.
- */
- public void reset() {
- done = false;
- tokenPosition = Optional.empty();
- state = AutomatonState.UNKNOWN;
- charPosition = 0;
- }
-
- /**
- * Process a character.
- *
- *
- * Process the next character in an effort to find the "prior token". Note that this is
- * expecting the processing sketch source code to be fed one character at a time
- * backwards from the starting position in code. This is because it is looking for the
- * first non-skip token immediately preceding a position in source.
- *
- *
- * @param input The next character to process.
- */
- public void step(char input) {
- switch(state) {
- case UNKNOWN: stepUnknown(input); break;
- case POSSIBLE_TOKEN: stepPossibleToken(input); break;
- case TOKEN_OR_MAYBE_SL_COMMENT: stepTokenOrMaybeSingleLineComment(input); break;
- case TOKEN_OR_MAYBE_COMMENT: stepTokenOrMaybeComment(input); break;
- case MULTI_LINE_COMMENT: stepMultiLineComment(input); break;
- case MAYBE_LEAVE_MULTI_LINE_COMMENT: stepMaybeLeaveMultiLineComment(input); break;
- case TOKEN: /* Already have token. Nothing to be done. */ break;
- }
-
- charPosition++;
- }
-
- /**
- * Process the next character while in the UNKNOWN state.
- *
- *
- * While not certain if looking at a skip or non-skip token, read the next character. If
- * whitespace, can ignore. If a forward slash, could indicate either a comment or a possible
- * token (move to TOKEN_OR_MAYBE_COMMENT). If anything else, may have found token but need to
- * ensure this line isn't part of a comment (move to POSSIBLE_TOKEN).
- *
- *
- * @param input The next character to process.
- */
- private void stepUnknown(char input) {
- if (isWhitespace(input)) {
- return;
- }
-
- tokenPosition = Optional.of(charPosition);
-
- if (input == '/') {
- state = AutomatonState.TOKEN_OR_MAYBE_COMMENT;
- } else {
- state = AutomatonState.POSSIBLE_TOKEN;
- }
- }
-
- /**
- * Process the next character while in the POSSIBLE_TOKEN state.
- *
- *
- * After having found a character that could indicate a token, need to ensure that the token
- * wasn't actually part of a single line comment ("//") so look for forward slashes (if found
- * move to TOKEN_OR_MAYBE_SL_COMMENT). If encountered a newline, the earlier found token was
- * not part of a comment so enter TOKEN state.
- *
- *
- * @param input The next character to process.
- */
- private void stepPossibleToken(char input) {
- if (input == '\n') {
- enterNonSkipTokenState();
- } else if (input == '/') {
- state = AutomatonState.TOKEN_OR_MAYBE_SL_COMMENT;
- }
-
- // Else stay put
- }
-
- /**
- * Process the next character while in the TOKEN_OR_MAYBE_SL_COMMENT state.
- *
- *
- * After having found a forward slash after encountering something else which may be a non-skip
- * token, one needs to check that it is preceded by another forward slash to have detected a
- * single line comment (return to UNKNOWN state). If found a new line, that forward slash was
- * actually a non-skip token itself so enter TOKEN state. Finally, if anything else, it is still
- * possible that we are traversing a single line comment so return to POSSIBLE_TOKEN state.
- *
- *
- * @param input The next character to process.
- */
- private void stepTokenOrMaybeSingleLineComment(char input) {
- if (input == '\n') {
- enterNonSkipTokenState();
- } else if (input == '/') {
- returnToUnknownState();
- } else {
- state = AutomatonState.POSSIBLE_TOKEN;
- }
- }
-
- /**
- * Process the next character while in the TOKEN_OR_MAYBE_COMMENT state.
- *
- *
- * After having found a forward slash without encountering something else that may be a non-skip
- * token: that forward slash is a non-skip token if preceded by a newline, could be a single
- * line comment if preceded by a forward slash, could be a multi-line comment if preceded
- * by an asterisk, or could by a non-skip token otherwise.
- *
- *
- * @param input The next character to process.
- */
- private void stepTokenOrMaybeComment(char input) {
- if (input == '\n') {
- enterNonSkipTokenState();
- } else if (input == '/') {
- returnToUnknownState();
- } else if (input == '*') {
- enterMultilineComment();
- } else {
- state = AutomatonState.POSSIBLE_TOKEN;
- }
- }
-
- /**
- * Process the next character while in the MULTI_LINE_COMMENT state.
- *
- *
- * Process the next character while traversing a multi-line comment. If an asterisk, we may be
- * encountering the end of the multiline comment (move to MAYBE_LEAVE_MULTI_LINE_COMMENT).
- * Otherwise, can ignore character.
- *
- *
- * @param input The next character to process.
- */
- private void stepMultiLineComment(char input) {
- if (input == '*') {
- state = AutomatonState.MAYBE_LEAVE_MULTI_LINE_COMMENT;
- }
-
- // else stay put
- }
-
- /**
- * Process the next character while in the MAYBE_LEAVE_MULTI_LINE_COMMENT state.
- *
- *
- * If already found an asterisk while inside a multi-line comment, one may be leaving the multi-
- * line comment depending on the next character. If forward slash, at end of comment (return to
- * UNKNOWN state). If another asterisk, could still end comment depending on next character
- * (stay in current state). Finally, if anything else, we are still in the body of the multi-
- * line comment and not about to leave (return to MULTI_LINE_COMMENT state).
- *
- *
- * @param input
- */
- private void stepMaybeLeaveMultiLineComment(char input) {
- if (input == '/') {
- state = AutomatonState.UNKNOWN;
- } else if (input != '*') {
- state = AutomatonState.MULTI_LINE_COMMENT;
- }
-
- // If * stay put
- }
-
- /**
- * Convenience function to set up internal FSA state when entering a multi-line comment.
- */
- private void enterMultilineComment() {
- tokenPosition = Optional.of(charPosition);
- state = AutomatonState.MULTI_LINE_COMMENT;
- }
-
- /**
- * Convenience function to set up internal FSA state when having found a non-skip token.
- */
- private void enterNonSkipTokenState() {
- done = true;
- state = AutomatonState.TOKEN;
- }
-
- /**
- * Convenience function to set up internal FSA state when entering UNKNOWN state.
- */
- private void returnToUnknownState() {
- tokenPosition = Optional.empty();
- state = AutomatonState.UNKNOWN;
- }
-
- /**
- * Convenience function which determines if a character is whitespace.
- *
- * @param input The character to test.
- * @return True if whitespace. False otherwise.
- */
- private boolean isWhitespace(char input) {
- return whitespacePattern.matcher("" + input).find();
- }
-
-}
diff --git a/java/test/processing/mode/java/ParserTests.java b/java/test/processing/mode/java/ParserTests.java
index 922b5bdeef..7be03a6d86 100644
--- a/java/test/processing/mode/java/ParserTests.java
+++ b/java/test/processing/mode/java/ParserTests.java
@@ -8,19 +8,14 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Optional;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.core.dom.ASTParser;
-import org.eclipse.jdt.core.dom.CompilationUnit;
import org.junit.BeforeClass;
import org.junit.Test;
import processing.app.SketchException;
import processing.mode.java.preproc.PreprocessorResult;
-import processing.mode.java.preproc.issue.PdePreprocessIssueException;
+import processing.mode.java.preproc.PdePreprocessIssueException;
public class ParserTests {
diff --git a/java/test/processing/mode/java/ProblemFactoryTest.java b/java/test/processing/mode/java/ProblemFactoryTest.java
index 7090590302..2b43f62c8f 100644
--- a/java/test/processing/mode/java/ProblemFactoryTest.java
+++ b/java/test/processing/mode/java/ProblemFactoryTest.java
@@ -6,13 +6,11 @@
import org.mockito.Mockito;
import processing.app.Problem;
import processing.app.ui.Editor;
-import processing.mode.java.preproc.issue.PdePreprocessIssue;
+import processing.mode.java.preproc.PdePreprocessIssue;
import java.util.ArrayList;
import java.util.List;
-import static org.junit.Assert.*;
-
public class ProblemFactoryTest {
private PdePreprocessIssue pdePreprocessIssue;
diff --git a/java/test/processing/mode/java/ProcessingTestUtil.java b/java/test/processing/mode/java/ProcessingTestUtil.java
index 97deb41475..cd8e43e9e7 100644
--- a/java/test/processing/mode/java/ProcessingTestUtil.java
+++ b/java/test/processing/mode/java/ProcessingTestUtil.java
@@ -2,7 +2,6 @@
import java.io.File;
import java.io.FileInputStream;
-import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Optional;
@@ -11,7 +10,7 @@
import processing.app.SketchException;
import processing.mode.java.preproc.PdePreprocessor;
import processing.mode.java.preproc.PreprocessorResult;
-import processing.mode.java.preproc.issue.PdePreprocessIssueException;
+import processing.mode.java.preproc.PdePreprocessIssueException;
public class ProcessingTestUtil {
diff --git a/java/test/processing/mode/java/preproc/issue/AssignmentMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/AssignmentMessageSimplifierStrategyTest.java
similarity index 58%
rename from java/test/processing/mode/java/preproc/issue/AssignmentMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/AssignmentMessageSimplifierStrategyTest.java
index 24d2bb6a1b..22a2f53df4 100644
--- a/java/test/processing/mode/java/preproc/issue/AssignmentMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/AssignmentMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -18,19 +20,19 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify(" int x =");
+ Optional msg = strategy.simplify(" int x =");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentDiamond() {
- Optional msg = strategy.simplify(" List x =");
+ Optional msg = strategy.simplify(" List x =");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("class {");
+ Optional msg = strategy.simplify("class {");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/BadIdentifierMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/BadIdentifierMessageSimplifierStrategyTest.java
similarity index 61%
rename from java/test/processing/mode/java/preproc/issue/BadIdentifierMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/BadIdentifierMessageSimplifierStrategyTest.java
index 523d7f517d..7a6e51997b 100644
--- a/java/test/processing/mode/java/preproc/issue/BadIdentifierMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/BadIdentifierMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -18,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("test(a,01a");
+ Optional msg = strategy.simplify("test(a,01a");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("class {");
+ Optional msg = strategy.simplify("class {");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/BadParamMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/BadParamMessageSimplifierStrategyTest.java
similarity index 55%
rename from java/test/processing/mode/java/preproc/issue/BadParamMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/BadParamMessageSimplifierStrategyTest.java
index 3204df4779..b0fb9a0b11 100644
--- a/java/test/processing/mode/java/preproc/issue/BadParamMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/BadParamMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -18,25 +20,25 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("void test (int x,\ny) \n{");
+ Optional msg = strategy.simplify("void test (int x,\ny) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentUnderscore() {
- Optional msg = strategy.simplify("void test (int x,\ny_y) \n{");
+ Optional msg = strategy.simplify("void test (int x,\ny_y) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentVarType() {
- Optional msg = strategy.simplify("void test (int x,\nint) \n{");
+ Optional msg = strategy.simplify("void test (int x,\nint) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("int x = y");
+ Optional msg = strategy.simplify("int x = y");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/ExtraneousInputMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/ExtraneousInputMessageSimplifierStrategyTest.java
similarity index 59%
rename from java/test/processing/mode/java/preproc/issue/ExtraneousInputMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/ExtraneousInputMessageSimplifierStrategyTest.java
index fce06fbfd7..69b8d09f09 100644
--- a/java/test/processing/mode/java/preproc/issue/ExtraneousInputMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/ExtraneousInputMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +21,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("extraneous input 'test' expecting ';'");
+ Optional msg = strategy.simplify("extraneous input 'test' expecting ';'");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("String x = \" \\\" \"");
+ Optional msg = strategy.simplify("String x = \" \\\" \"");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/KnownMissingMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/KnownMissingMessageSimplifierStrategyTest.java
similarity index 59%
rename from java/test/processing/mode/java/preproc/issue/KnownMissingMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/KnownMissingMessageSimplifierStrategyTest.java
index 40efe75365..587cd45c42 100644
--- a/java/test/processing/mode/java/preproc/issue/KnownMissingMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/KnownMissingMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -18,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("missing ';' at 'addCircle'");
+ Optional msg = strategy.simplify("missing ';' at 'addCircle'");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("String x = \" \\\" \"");
+ Optional msg = strategy.simplify("String x = \" \\\" \"");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MessageSimplifierUtilTest.java b/java/test/processing/mode/java/preproc/MessageSimplifierUtilTest.java
similarity index 83%
rename from java/test/processing/mode/java/preproc/issue/MessageSimplifierUtilTest.java
rename to java/test/processing/mode/java/preproc/MessageSimplifierUtilTest.java
index 0072d2cb47..d663964d1c 100644
--- a/java/test/processing/mode/java/preproc/issue/MessageSimplifierUtilTest.java
+++ b/java/test/processing/mode/java/preproc/MessageSimplifierUtilTest.java
@@ -1,8 +1,8 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Test;
-import processing.mode.java.preproc.issue.PreprocessIssueMessageSimplifier;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
public class MessageSimplifierUtilTest {
diff --git a/java/test/processing/mode/java/preproc/issue/MismatchedInputMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MismatchedInputMessageSimplifierStrategyTest.java
similarity index 52%
rename from java/test/processing/mode/java/preproc/issue/MismatchedInputMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MismatchedInputMessageSimplifierStrategyTest.java
index da38118bd5..c3da11d8db 100644
--- a/java/test/processing/mode/java/preproc/issue/MismatchedInputMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MismatchedInputMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +21,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("mismatched input 'final' expecting {'instanceof', ';', ',', '.', '>', '<', '==', '<=', '>=', '!=', '&&', '||', '++', '--', '+', '-', '*', '/', '&', '|', '^', '%', '::'}");
+ Optional msg = strategy.simplify("mismatched input 'final' expecting {'instanceof', ';', ',', '.', '>', '<', '==', '<=', '>=', '!=', '&&', '||', '++', '--', '+', '-', '*', '/', '&', '|', '^', '%', '::'}");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("String x = \" \\\" \"");
+ Optional msg = strategy.simplify("String x = \" \\\" \"");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingChevMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingChevMessageSimplifierStrategyTest.java
similarity index 60%
rename from java/test/processing/mode/java/preproc/issue/MissingChevMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingChevMessageSimplifierStrategyTest.java
index a40b9eef36..9b6d4d6c8a 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingChevMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingChevMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("class Test msg = strategy.simplify("class Test msg = strategy.simplify("class {");
+ Optional msg = strategy.simplify("class {");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingClassNameMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingClassNameMessageSimplifierStrategyTest.java
similarity index 58%
rename from java/test/processing/mode/java/preproc/issue/MissingClassNameMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingClassNameMessageSimplifierStrategyTest.java
index 94b2d99609..ebbfe6659c 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingClassNameMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingClassNameMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,19 +20,19 @@ public void setup() {
@Test
public void testPresentExtends() {
- Optional msg = strategy.simplify("class extends Base\n{");
+ Optional msg = strategy.simplify("class extends Base\n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentNoExtends() {
- Optional msg = strategy.simplify("class \n{");
+ Optional msg = strategy.simplify("class \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("int x = y");
+ Optional msg = strategy.simplify("int x = y");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingCurlyMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingCurlyMessageSimplifierStrategyTest.java
similarity index 60%
rename from java/test/processing/mode/java/preproc/issue/MissingCurlyMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingCurlyMessageSimplifierStrategyTest.java
index 81b005f0de..c63e33f134 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingCurlyMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingCurlyMessageSimplifierStrategyTest.java
@@ -1,10 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
-import processing.mode.java.preproc.issue.PreprocessIssueMessageSimplifier;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -20,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("class Test {");
+ Optional msg = strategy.simplify("class Test {");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("class Test { }");
+ Optional msg = strategy.simplify("class Test { }");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingDoubleQuoteMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingDoubleQuoteMessageSimplifierStrategyTest.java
similarity index 59%
rename from java/test/processing/mode/java/preproc/issue/MissingDoubleQuoteMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingDoubleQuoteMessageSimplifierStrategyTest.java
index 17b3d47a37..bb4e79c3bb 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingDoubleQuoteMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingDoubleQuoteMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("String x = \" \" \"");
+ Optional msg = strategy.simplify("String x = \" \" \"");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("String x = \" \\\" \"");
+ Optional msg = strategy.simplify("String x = \" \\\" \"");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingGenericTypeMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingGenericTypeMessageSimplifierStrategyTest.java
similarity index 62%
rename from java/test/processing/mode/java/preproc/issue/MissingGenericTypeMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingGenericTypeMessageSimplifierStrategyTest.java
index 2393a586bd..e6847470f9 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingGenericTypeMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingGenericTypeMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("<>'");
+ Optional msg = strategy.simplify("<>'");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("class {");
+ Optional msg = strategy.simplify("class {");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingIdentifierMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingIdentifierMessageSimplifierStrategyTest.java
similarity index 60%
rename from java/test/processing/mode/java/preproc/issue/MissingIdentifierMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingIdentifierMessageSimplifierStrategyTest.java
index 9333b961d2..924aec011f 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingIdentifierMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingIdentifierMessageSimplifierStrategyTest.java
@@ -1,8 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +21,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("Missing identifier at ';'");
+ Optional msg = strategy.simplify("Missing identifier at ';'");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("String x = \" \\\" \"");
+ Optional msg = strategy.simplify("String x = \" \\\" \"");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingMethodNameMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingMethodNameMessageSimplifierStrategyTest.java
similarity index 56%
rename from java/test/processing/mode/java/preproc/issue/MissingMethodNameMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingMethodNameMessageSimplifierStrategyTest.java
index ac9e315e3a..e94dba63bd 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingMethodNameMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingMethodNameMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,25 +20,25 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("void (int x) \n{");
+ Optional msg = strategy.simplify("void (int x) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentNoSpace() {
- Optional msg = strategy.simplify("test(int x) \n{");
+ Optional msg = strategy.simplify("test(int x) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testPresentUnderscore() {
- Optional msg = strategy.simplify("void (int x_y) \n{");
+ Optional msg = strategy.simplify("void (int x_y) \n{");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("int x = y");
+ Optional msg = strategy.simplify("int x = y");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingParenMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingParenMessageSimplifierStrategyTest.java
similarity index 59%
rename from java/test/processing/mode/java/preproc/issue/MissingParenMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingParenMessageSimplifierStrategyTest.java
index c71a2070a0..f6e8e3de27 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingParenMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingParenMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("int x = ((5 + 4) / 3");
+ Optional msg = strategy.simplify("int x = ((5 + 4) / 3");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("int x = (y/5)/(\n4)");
+ Optional msg = strategy.simplify("int x = (y/5)/(\n4)");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingSingleQuoteMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingSingleQuoteMessageSimplifierStrategyTest.java
similarity index 60%
rename from java/test/processing/mode/java/preproc/issue/MissingSingleQuoteMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingSingleQuoteMessageSimplifierStrategyTest.java
index 68cc1e15b2..0c53c1df65 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingSingleQuoteMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingSingleQuoteMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -18,13 +19,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("char x = '");
+ Optional msg = strategy.simplify("char x = '");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("char x = '\\''");
+ Optional msg = strategy.simplify("char x = '\\''");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/issue/MissingVariableNameMessageSimplifierStrategyTest.java b/java/test/processing/mode/java/preproc/MissingVariableNameMessageSimplifierStrategyTest.java
similarity index 61%
rename from java/test/processing/mode/java/preproc/issue/MissingVariableNameMessageSimplifierStrategyTest.java
rename to java/test/processing/mode/java/preproc/MissingVariableNameMessageSimplifierStrategyTest.java
index 7f95a65c6c..e2c69757a4 100644
--- a/java/test/processing/mode/java/preproc/issue/MissingVariableNameMessageSimplifierStrategyTest.java
+++ b/java/test/processing/mode/java/preproc/MissingVariableNameMessageSimplifierStrategyTest.java
@@ -1,9 +1,10 @@
-package processing.mode.java.preproc.issue;
+package processing.mode.java.preproc;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
import java.util.Optional;
@@ -19,13 +20,13 @@ public void setup() {
@Test
public void testPresent() {
- Optional msg = strategy.simplify("char = ';");
+ Optional msg = strategy.simplify("char = ';");
Assert.assertTrue(msg.isPresent());
}
@Test
public void testNotPresent() {
- Optional msg = strategy.simplify("class test {");
+ Optional msg = strategy.simplify("class test {");
Assert.assertTrue(msg.isEmpty());
}
diff --git a/java/test/processing/mode/java/preproc/util/IssueLocationFactoryTest.java b/java/test/processing/mode/java/preproc/util/IssueLocationFactoryTest.java
index 553ce869ea..67ad299745 100644
--- a/java/test/processing/mode/java/preproc/util/IssueLocationFactoryTest.java
+++ b/java/test/processing/mode/java/preproc/util/IssueLocationFactoryTest.java
@@ -3,15 +3,13 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
-import processing.mode.java.preproc.issue.IssueLocation;
-import processing.mode.java.preproc.issue.IssueLocationFactory;
-import processing.mode.java.preproc.issue.IssueMessageSimplification;
+import processing.mode.java.preproc.PdeIssueEmitter;
public class IssueLocationFactoryTest {
private String source;
- private IssueLocation issueLocation;
+ private PdeIssueEmitter.IssueLocation issueLocation;
@Before
public void setup() {
@@ -33,8 +31,8 @@ public void setup() {
@Test
public void getLineWithOffsetApplies() {
- issueLocation = IssueLocationFactory.getLineWithOffset(
- new IssueMessageSimplification("test message", true),
+ issueLocation = PdeIssueEmitter.IssueLocationFactory.getLineWithOffset(
+ new PdeIssueEmitter.IssueMessageSimplification("test message", true),
15,
0,
source
@@ -46,8 +44,8 @@ public void getLineWithOffsetApplies() {
@Test
public void getLineWithOffsetNotApplies() {
- issueLocation = IssueLocationFactory.getLineWithOffset(
- new IssueMessageSimplification("test message", false),
+ issueLocation = PdeIssueEmitter.IssueLocationFactory.getLineWithOffset(
+ new PdeIssueEmitter.IssueMessageSimplification("test message", false),
15,
0,
source
@@ -59,8 +57,8 @@ public void getLineWithOffsetNotApplies() {
@Test
public void getLineWithOffsetEndWhite() {
- issueLocation = IssueLocationFactory.getLineWithOffset(
- new IssueMessageSimplification("test message", true),
+ issueLocation = PdeIssueEmitter.IssueLocationFactory.getLineWithOffset(
+ new PdeIssueEmitter.IssueMessageSimplification("test message", true),
14,
0,
"\n\n\n\n\n\n\n\n\n\n\nnoFill()\nellipse(50,50,50,50)\n"
diff --git a/java/test/processing/mode/java/preproc/util/PreprocessIssueMessageSimplifierTest.java b/java/test/processing/mode/java/preproc/util/PreprocessIssueMessageSimplifierTest.java
index 8131ba96e1..617313b468 100644
--- a/java/test/processing/mode/java/preproc/util/PreprocessIssueMessageSimplifierTest.java
+++ b/java/test/processing/mode/java/preproc/util/PreprocessIssueMessageSimplifierTest.java
@@ -2,7 +2,7 @@
import org.junit.Assert;
import org.junit.Test;
-import processing.mode.java.preproc.issue.PreprocessIssueMessageSimplifier;
+import processing.mode.java.preproc.PreprocessIssueMessageSimplifier;
public class PreprocessIssueMessageSimplifierTest {