| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 0ebd09e commit 9efa410
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,6 +48,7 @@ | |||
| 48 | 48 | import java.util.concurrent.atomic.AtomicReference; | |
| 49 | 49 | import java.util.function.Consumer; | |
| 50 | 50 | import java.util.function.Predicate; | |
| 51 | + import java.util.regex.Matcher; | ||
| 51 | 52 | import java.util.regex.Pattern; | |
| 52 | 53 | import java.util.stream.Collectors; | |
| 53 | 54 | ||
@@ -1083,32 +1084,18 @@ private void handleSketchProblems(PreprocessedSketch ps) { | |||
| 1083 | 1084 | ||
| 1084 | 1085 | IProblem[] iproblems = ps.compilationUnit.getProblems(); | |
| 1085 | 1086 | ||
| 1086 | - { // Handle missing brace problems | ||
| 1087 | - IProblem missingBraceProblem = Arrays.stream(iproblems) | ||
| 1088 | - .filter(ErrorChecker::isMissingBraceProblem) | ||
| 1089 | - .findFirst() | ||
| 1090 | - // Ignore if it is at the end of file | ||
| 1091 | - .filter(p -> p.getSourceEnd() + 1 < ps.javaCode.length()) | ||
| 1092 | - // Ignore if the tab number does not match our detected tab number | ||
| 1093 | - .filter(p -> ps.missingBraceProblems.isEmpty() || | ||
| 1094 | - ps.missingBraceProblems.get(0).getTabIndex() == | ||
| 1095 | - ps.mapJavaToSketch(p.getSourceStart(), p.getSourceEnd()+1).tabIndex | ||
| 1096 | - ) | ||
| 1097 | - .orElse(null); | ||
| 1098 | - | ||
| 1099 | - // If there is missing brace ignore all other problems | ||
| 1100 | - if (missingBraceProblem != null) { | ||
| 1101 | - // Prefer ECJ problem, shows location more accurately | ||
| 1102 | - iproblems = new IProblem[]{missingBraceProblem}; | ||
| 1103 | - } else if (!ps.missingBraceProblems.isEmpty()) { | ||
| 1104 | - // Fallback to manual detection | ||
| 1105 | - problems.addAll(ps.missingBraceProblems); | ||
| 1106 | - } | ||
| 1087 | + { // Check for curly quotes | ||
| 1088 | + List<JavaProblem> curlyQuoteProblems = checkForCurlyQuotes(ps); | ||
| 1089 | + problems.addAll(curlyQuoteProblems); | ||
| 1107 | 1090 | } | |
| 1108 | 1091 | ||
| 1109 | - AtomicReference<ClassPath> searchClassPath = new AtomicReference<>(null); | ||
| 1092 | + if (problems.isEmpty()) { // Check for missing braces | ||
| 1093 | + List<JavaProblem> missingBraceProblems = checkForMissingBraces(ps); | ||
| 1094 | + problems.addAll(missingBraceProblems); | ||
| 1095 | + } | ||
| 1110 | 1096 | ||
| 1111 | 1097 | if (problems.isEmpty()) { | |
| 1098 | + AtomicReference<ClassPath> searchClassPath = new AtomicReference<>(null); | ||
| 1112 | 1099 | List<Problem> cuProblems = Arrays.stream(iproblems) | |
| 1113 | 1100 | // Filter Warnings if they are not enabled | |
| 1114 | 1101 | .filter(iproblem -> !(iproblem.isWarning() && !JavaMode.warningsEnabled)) | |
@@ -1121,17 +1108,10 @@ private void handleSketchProblems(PreprocessedSketch ps) { | |||
| 1121 | 1108 | .contains("Syntax error, insert \":: IdentifierOrNew\"")) | |
| 1122 | 1109 | // Transform into our Problems | |
| 1123 | 1110 | .map(iproblem -> { | |
| 1124 | - int start = iproblem.getSourceStart(); | ||
| 1125 | - int stop = iproblem.getSourceEnd() + 1; // make it exclusive | ||
| 1126 | - SketchInterval in = ps.mapJavaToSketch(start, stop); | ||
| 1127 | - if (in == SketchInterval.BEFORE_START) return null; | ||
| 1128 | - String badCode = ps.pdeCode.substring(in.startPdeOffset, in.stopPdeOffset); | ||
| 1129 | - int line = ps.tabOffsetToTabLine(in.tabIndex, in.startTabOffset); | ||
| 1130 | - JavaProblem p = JavaProblem.fromIProblem(iproblem, in.tabIndex, line, badCode); | ||
| 1131 | - p.setPDEOffsets(in.startTabOffset, in.stopTabOffset); | ||
| 1111 | + JavaProblem p = convertIProblem(iproblem, ps); | ||
| 1132 | 1112 | ||
| 1133 | 1113 | // Handle import suggestions | |
| 1134 | - if (JavaMode.importSuggestEnabled && isUndefinedTypeProblem(iproblem)) { | ||
| 1114 | + if (p != null && JavaMode.importSuggestEnabled && isUndefinedTypeProblem(iproblem)) { | ||
| 1135 | 1115 | ClassPath cp = searchClassPath.updateAndGet(prev -> prev != null ? | |
| 1136 | 1116 | prev : new ClassPathFactory().createFromPaths(ps.searchClassPathArray)); | |
| 1137 | 1117 | String[] s = suggCache.computeIfAbsent(iproblem.getArguments()[0], | |
@@ -1161,6 +1141,16 @@ private void handleSketchProblems(PreprocessedSketch ps) { | |||
| 1161 | 1141 | TimeUnit.MILLISECONDS); | |
| 1162 | 1142 | } | |
| 1163 | 1143 | ||
| 1144 | + static private JavaProblem convertIProblem(IProblem iproblem, PreprocessedSketch ps) { | ||
| 1145 | + SketchInterval in = ps.mapJavaToSketch(iproblem); | ||
| 1146 | + if (in == SketchInterval.BEFORE_START) return null; | ||
| 1147 | + String badCode = ps.pdeCode.substring(in.startPdeOffset, in.stopPdeOffset); | ||
| 1148 | + int line = ps.tabOffsetToTabLine(in.tabIndex, in.startTabOffset); | ||
| 1149 | + JavaProblem p = JavaProblem.fromIProblem(iproblem, in.tabIndex, line, badCode); | ||
| 1150 | + p.setPDEOffsets(in.startTabOffset, in.stopTabOffset); | ||
| 1151 | + return p; | ||
| 1152 | + } | ||
| 1153 | + | ||
| 1164 | 1154 | ||
| 1165 | 1155 | static private boolean isUndefinedTypeProblem(IProblem iproblem) { | |
| 1166 | 1156 | int id = iproblem.getID(); | |
@@ -1186,6 +1176,119 @@ static private boolean isMissingBraceProblem(IProblem iproblem) { | |||
| 1186 | 1176 | } | |
| 1187 | 1177 | ||
| 1188 | 1178 | ||
| 1179 | + private static final Pattern CURLY_QUOTE_REGEX = | ||
| 1180 | + Pattern.compile("([“”‘’])", Pattern.UNICODE_CHARACTER_CLASS); | ||
| 1181 | + | ||
| 1182 | + static private List<JavaProblem> checkForCurlyQuotes(PreprocessedSketch ps) { | ||
| 1183 | + List<JavaProblem> problems = new ArrayList<>(0); | ||
| 1184 | + | ||
| 1185 | + // Go through the scrubbed code and look for curly quotes (they should not be any) | ||
| 1186 | + Matcher matcher = CURLY_QUOTE_REGEX.matcher(ps.scrubbedPdeCode); | ||
| 1187 | + while (matcher.find()) { | ||
| 1188 | + int pdeOffset = matcher.start(); | ||
| 1189 | + String q = matcher.group(); | ||
| 1190 | + | ||
| 1191 | + int tabIndex = ps.pdeOffsetToTabIndex(pdeOffset); | ||
| 1192 | + int tabOffset = ps.pdeOffsetToTabOffset(tabIndex, pdeOffset); | ||
| 1193 | + int tabLine = ps.tabOffsetToTabLine(tabIndex, tabOffset); | ||
| 1194 | + | ||
| 1195 | + String message = Language.interpolate("editor.status.bad_curly_quote", q); | ||
| 1196 | + JavaProblem problem = new JavaProblem(message, JavaProblem.ERROR, tabIndex, tabLine, 10); | ||
| 1197 | + problem.setPDEOffsets(tabOffset, tabOffset+1); | ||
| 1198 | + | ||
| 1199 | + problems.add(problem); | ||
| 1200 | + } | ||
| 1201 | + | ||
| 1202 | + | ||
| 1203 | + // Go through iproblems and look for problems involving curly quotes | ||
| 1204 | + List<JavaProblem> problems2 = new ArrayList<>(0); | ||
| 1205 | + IProblem[] iproblems = ps.compilationUnit.getProblems(); | ||
| 1206 | + | ||
| 1207 | + for (IProblem iproblem : iproblems) { | ||
| 1208 | + switch (iproblem.getID()) { | ||
| 1209 | + case IProblem.ParsingErrorDeleteToken: | ||
| 1210 | + case IProblem.ParsingErrorDeleteTokens: | ||
| 1211 | + case IProblem.ParsingErrorInvalidToken: | ||
| 1212 | + case IProblem.ParsingErrorReplaceTokens: | ||
| 1213 | + case IProblem.UnterminatedString: | ||
| 1214 | + SketchInterval in = ps.mapJavaToSketch(iproblem); | ||
| 1215 | + if (in == SketchInterval.BEFORE_START) continue; | ||
| 1216 | + String badCode = ps.pdeCode.substring(in.startPdeOffset, in.stopPdeOffset); | ||
| 1217 | + matcher.reset(badCode); | ||
| 1218 | + while (matcher.find()) { | ||
| 1219 | + int offset = matcher.start(); | ||
| 1220 | + String q = matcher.group(); | ||
| 1221 | + int tabStart = in.startTabOffset + offset; | ||
| 1222 | + int tabStop = tabStart + 1; | ||
| 1223 | + // Prevent duplicate problems | ||
| 1224 | + if (problems.stream().noneMatch(p -> p.getStartOffset() == tabStart)) { | ||
| 1225 | + int line = ps.tabOffsetToTabLine(in.tabIndex, tabStart); | ||
| 1226 | + String message; | ||
| 1227 | + if (iproblem.getID() == IProblem.UnterminatedString) { | ||
| 1228 | + message = Language.interpolate("editor.status.unterm_string_curly", q); | ||
| 1229 | + } else { | ||
| 1230 | + message = Language.interpolate("editor.status.bad_curly_quote", q); | ||
| 1231 | + } | ||
| 1232 | + JavaProblem p = new JavaProblem(message, JavaProblem.ERROR, in.tabIndex, line, 10); | ||
| 1233 | + p.setPDEOffsets(tabStart, tabStop); | ||
| 1234 | + problems2.add(p); | ||
| 1235 | + } | ||
| 1236 | + } | ||
| 1237 | + } | ||
| 1238 | + } | ||
| 1239 | + | ||
| 1240 | + problems.addAll(problems2); | ||
| 1241 | + | ||
| 1242 | + return problems; | ||
| 1243 | + } | ||
| 1244 | + | ||
| 1245 | + | ||
| 1246 | + static private List<JavaProblem> checkForMissingBraces(PreprocessedSketch ps) { | ||
| 1247 | + List<JavaProblem> problems = new ArrayList<>(0); | ||
| 1248 | + for (int tabIndex = 0; tabIndex < ps.tabStartOffsets.length; tabIndex++) { | ||
| 1249 | + int tabStartOffset = ps.tabStartOffsets[tabIndex]; | ||
| 1250 | + int tabEndOffset = (tabIndex < ps.tabStartOffsets.length - 1) ? | ||
| 1251 | + ps.tabStartOffsets[tabIndex + 1] : ps.scrubbedPdeCode.length(); | ||
| 1252 | + int[] braceResult = SourceUtils.checkForMissingBraces(ps.scrubbedPdeCode, tabStartOffset, tabEndOffset); | ||
| 1253 | + if (braceResult[0] != 0) { | ||
| 1254 | + JavaProblem problem = | ||
| 1255 | + new JavaProblem(braceResult[0] < 0 | ||
| 1256 | + ? Language.interpolate("editor.status.missing.left_curly_bracket") | ||
| 1257 | + : Language.interpolate("editor.status.missing.right_curly_bracket"), | ||
| 1258 | + JavaProblem.ERROR, tabIndex, braceResult[1], 8); | ||
| 1259 | + problem.setPDEOffsets(braceResult[3], braceResult[3] + 1); | ||
| 1260 | + problems.add(problem); | ||
| 1261 | + } | ||
| 1262 | + } | ||
| 1263 | + | ||
| 1264 | + if (problems.isEmpty()) { | ||
| 1265 | + return problems; | ||
| 1266 | + } | ||
| 1267 | + | ||
| 1268 | + int problemTabIndex = problems.get(0).getTabIndex(); | ||
| 1269 | + | ||
| 1270 | + IProblem missingBraceProblem = Arrays.stream(ps.compilationUnit.getProblems()) | ||
| 1271 | + .filter(ErrorChecker::isMissingBraceProblem) | ||
| 1272 | + // Ignore if it is at the end of file | ||
| 1273 | + .filter(p -> p.getSourceEnd() + 1 < ps.javaCode.length()) | ||
| 1274 | + // Ignore if the tab number does not match our detected tab number | ||
| 1275 | + .filter(p -> problemTabIndex == ps.mapJavaToSketch(p).tabIndex) | ||
| 1276 | + .findFirst() | ||
| 1277 | + .orElse(null); | ||
| 1278 | + | ||
| 1279 | + // Prefer ECJ problem, shows location more accurately | ||
| 1280 | + if (missingBraceProblem != null) { | ||
| 1281 | + JavaProblem p = convertIProblem(missingBraceProblem, ps); | ||
| 1282 | + if (p != null) { | ||
| 1283 | + problems.clear(); | ||
| 1284 | + problems.add(p); | ||
| 1285 | + } | ||
| 1286 | + } | ||
| 1287 | + | ||
| 1288 | + return problems; | ||
| 1289 | + } | ||
| 1290 | + | ||
| 1291 | + | ||
| 1189 | 1292 | static public String[] getImportSuggestions(ClassPath cp, String className) { | |
| 1190 | 1293 | RegExpResourceFilter regf = new RegExpResourceFilter( | |
| 1191 | 1294 | Pattern.compile(".*"), | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | 3 | import com.google.classpath.ClassPath; | |
| 4 | 4 | ||
| 5 | + import org.eclipse.jdt.core.compiler.IProblem; | ||
| 5 | 6 | import org.eclipse.jdt.core.dom.ASTNode; | |
| 6 | 7 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
| 7 | 8 | ||
@@ -11,7 +12,6 @@ | |||
| 11 | 12 | import java.util.Collections; | |
| 12 | 13 | import java.util.List; | |
| 13 | 14 | ||
| 14 | - import processing.app.Problem; | ||
| 15 | 15 | import processing.app.Sketch; | |
| 16 | 16 | import processing.core.PApplet; | |
| 17 | 17 | import processing.mode.java.pdex.TextTransform.OffsetMapper; | |
@@ -30,13 +30,12 @@ public class PreprocessedSketch { | |||
| 30 | 30 | ||
| 31 | 31 | public final int[] tabStartOffsets; | |
| 32 | 32 | ||
| 33 | + public final String scrubbedPdeCode; | ||
| 33 | 34 | public final String pdeCode; | |
| 34 | 35 | public final String javaCode; | |
| 35 | 36 | ||
| 36 | 37 | public final OffsetMapper offsetMapper; | |
| 37 | 38 | ||
| 38 | - public final List<Problem> missingBraceProblems; | ||
| 39 | - | ||
| 40 | 39 | public final boolean hasSyntaxErrors; | |
| 41 | 40 | public final boolean hasCompilationErrors; | |
| 42 | 41 | ||
@@ -84,6 +83,12 @@ public SketchInterval mapJavaToSketch(ASTNode node) { | |||
| 84 | 83 | } | |
| 85 | 84 | ||
| 86 | 85 | ||
| 86 | + public SketchInterval mapJavaToSketch(IProblem iproblem) { | ||
| 87 | + return mapJavaToSketch(iproblem.getSourceStart(), | ||
| 88 | + iproblem.getSourceEnd() + 1); // make it exclusive | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + | ||
| 87 | 92 | public SketchInterval mapJavaToSketch(int startJavaOffset, int stopJavaOffset) { | |
| 88 | 93 | int length = stopJavaOffset - startJavaOffset; | |
| 89 | 94 | int startPdeOffset = javaOffsetToPdeOffset(startJavaOffset); | |
@@ -120,7 +125,7 @@ private int javaOffsetToPdeOffset(int javaOffset) { | |||
| 120 | 125 | } | |
| 121 | 126 | ||
| 122 | 127 | ||
| 123 | - private int pdeOffsetToTabIndex(int pdeOffset) { | ||
| 128 | + public int pdeOffsetToTabIndex(int pdeOffset) { | ||
| 124 | 129 | pdeOffset = Math.max(0, pdeOffset); | |
| 125 | 130 | int tab = Arrays.binarySearch(tabStartOffsets, pdeOffset); | |
| 126 | 131 | if (tab < 0) { | |
@@ -130,7 +135,7 @@ private int pdeOffsetToTabIndex(int pdeOffset) { | |||
| 130 | 135 | } | |
| 131 | 136 | ||
| 132 | 137 | ||
| 133 | - private int pdeOffsetToTabOffset(int tabIndex, int pdeOffset) { | ||
| 138 | + public int pdeOffsetToTabOffset(int tabIndex, int pdeOffset) { | ||
| 134 | 139 | int tabStartOffset = tabStartOffsets[clipTabIndex(tabIndex)]; | |
| 135 | 140 | return pdeOffset - tabStartOffset; | |
| 136 | 141 | } | |
@@ -210,13 +215,12 @@ public static class Builder { | |||
| 210 | 215 | ||
| 211 | 216 | public int[] tabStartOffsets = new int[0]; | |
| 212 | 217 | ||
| 218 | + public String scrubbedPdeCode; | ||
| 213 | 219 | public String pdeCode; | |
| 214 | 220 | public String javaCode; | |
| 215 | 221 | ||
| 216 | 222 | public OffsetMapper offsetMapper; | |
| 217 | 223 | ||
| 218 | - public final List<Problem> missingBraceProblems = new ArrayList<>(0); | ||
| 219 | - | ||
| 220 | 224 | public boolean hasSyntaxErrors; | |
| 221 | 225 | public boolean hasCompilationErrors; | |
| 222 | 226 | ||
@@ -246,13 +250,12 @@ private PreprocessedSketch(Builder b) { | |||
| 246 | 250 | ||
| 247 | 251 | tabStartOffsets = b.tabStartOffsets; | |
| 248 | 252 | ||
| 253 | + scrubbedPdeCode = b.scrubbedPdeCode; | ||
| 249 | 254 | pdeCode = b.pdeCode; | |
| 250 | 255 | javaCode = b.javaCode; | |
| 251 | 256 | ||
| 252 | 257 | offsetMapper = b.offsetMapper != null ? b.offsetMapper : OffsetMapper.EMPTY_MAPPER; | |
| 253 | 258 | ||
| 254 | - missingBraceProblems = Collections.unmodifiableList(b.missingBraceProblems); | ||
| 255 | - | ||
| 256 | 259 | hasSyntaxErrors = b.hasSyntaxErrors; | |
| 257 | 260 | hasCompilationErrors = b.hasCompilationErrors; | |
| 258 | 261 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -312,6 +312,8 @@ private PreprocessedSketch preprocessSketch(PreprocessedSketch prevResult) { | |||
| 312 | 312 | ||
| 313 | 313 | SourceUtils.scrubCommentsAndStrings(workBuffer); | |
| 314 | 314 | ||
| 315 | + result.scrubbedPdeCode = workBuffer.toString(); | ||
| 316 | + | ||
| 315 | 317 | Mode sketchMode = PdePreprocessor.parseMode(workBuffer); | |
| 316 | 318 | ||
| 317 | 319 | // Prepare transforms to convert pde code into parsable code | |
@@ -394,15 +396,6 @@ private PreprocessedSketch preprocessSketch(PreprocessedSketch prevResult) { | |||
| 394 | 396 | } | |
| 395 | 397 | } | |
| 396 | 398 | ||
| 397 | - { // Check for missing braces | ||
| 398 | - List<JavaProblem> missingBraceProblems = | ||
| 399 | - SourceUtils.checkForMissingBraces(workBuffer, result.tabStartOffsets); | ||
| 400 | - if (!missingBraceProblems.isEmpty()) { | ||
| 401 | - result.missingBraceProblems.addAll(missingBraceProblems); | ||
| 402 | - result.hasSyntaxErrors = true; | ||
| 403 | - } | ||
| 404 | - } | ||
| 405 | - | ||
| 406 | 399 | // Transform code to parsable state | |
| 407 | 400 | String parsableStage = toParsable.apply(); | |
| 408 | 401 | OffsetMapper parsableMapper = toParsable.getMapper(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -331,27 +331,9 @@ static public void scrubCommentsAndStrings(StringBuilder p) { | |||
| 331 | 331 | ||
| 332 | 332 | } | |
| 333 | 333 | ||
| 334 | - static public List<JavaProblem> checkForMissingBraces(StringBuilder p, int[] tabStartOffsets) { | ||
| 335 | - List<JavaProblem> problems = new ArrayList<>(0); | ||
| 336 | - for (int tabIndex = 0; tabIndex < tabStartOffsets.length; tabIndex++) { | ||
| 337 | - int tabStartOffset = tabStartOffsets[tabIndex]; | ||
| 338 | - int tabEndOffset = (tabIndex < tabStartOffsets.length - 1) ? | ||
| 339 | - tabStartOffsets[tabIndex + 1] : p.length(); | ||
| 340 | - int[] braceResult = checkForMissingBraces(p, tabStartOffset, tabEndOffset); | ||
| 341 | - if (braceResult[0] != 0) { | ||
| 342 | - JavaProblem problem = | ||
| 343 | - new JavaProblem(braceResult[0] < 0 | ||
| 344 | - ? "Found one too many } characters without { to match it." | ||
| 345 | - : "Found one too many { characters without } to match it.", | ||
| 346 | - JavaProblem.ERROR, tabIndex, braceResult[1], 8); | ||
| 347 | - problem.setPDEOffsets(braceResult[3], braceResult[3] + 1); | ||
| 348 | - problems.add(problem); | ||
| 349 | - } | ||
| 350 | - } | ||
| 351 | - return problems; | ||
| 352 | - } | ||
| 353 | - | ||
| 354 | 334 | ||
| 335 | + // TODO: move this to a better place when JavaBuild starts using JDT and we | ||
| 336 | + // don't need to check errors at two different places [jv 2017-09-19] | ||
| 355 | 337 | /** | |
| 356 | 338 | * Checks a single code fragment (such as a tab) for non-matching braces. | |
| 357 | 339 | * Broken out to allow easy use in JavaBuild. | |
| Back | FazBrowse Home | New Git URL |
0 commit comments