diff --git a/java/src/processing/mode/java/pdex/ASTGenerator.java b/java/src/processing/mode/java/pdex/ASTGenerator.java index 66b68927e..00aadd724 100644 --- a/java/src/processing/mode/java/pdex/ASTGenerator.java +++ b/java/src/processing/mode/java/pdex/ASTGenerator.java @@ -1173,7 +1173,6 @@ public class ASTGenerator { if (editor.hasJavaTabs()) return; // show usage disabled if java tabs PreprocessedSketch ps = errorCheckerService.latestResult; - if (ps.hasSyntaxErrors) return; // Map offsets int startJavaOffset = ps.tabOffsetToJavaOffset(tabIndex, startTabOffset); @@ -1193,7 +1192,6 @@ public class ASTGenerator { public void handleShowUsage(IBinding binding) { PreprocessedSketch ps = errorCheckerService.latestResult; - if (ps.hasSyntaxErrors) return; String bindingKey = binding.getKey(); diff --git a/java/src/processing/mode/java/pdex/ErrorCheckerService.java b/java/src/processing/mode/java/pdex/ErrorCheckerService.java index fd2a4f689..4fdc077bf 100644 --- a/java/src/processing/mode/java/pdex/ErrorCheckerService.java +++ b/java/src/processing/mode/java/pdex/ErrorCheckerService.java @@ -326,8 +326,7 @@ public class ErrorCheckerService { result.tabStarts = tabStartsList.array(); String pdeStage = result.pdeCode = workBuffer.toString(); - String syntaxStage; - String javaStage; + char[] javaStageChars; { // Prepare core and default imports // TODO: do this only once @@ -355,8 +354,6 @@ public class ErrorCheckerService { // TODO: convert unicode escapes to chars - CompilationUnit syntaxCU; - {{ // SYNTAX CHECK try { @@ -377,46 +374,13 @@ public class ErrorCheckerService { syntaxMapping.addAll(SourceUtils.replaceHexLiterals(workBuffer)); syntaxMapping.addAll(SourceUtils.wrapSketch(mode, className, workBuffer.length())); - // TODO: all imports are parsed now, check if they need to be filtered somehow - - // Transform code - syntaxStage = syntaxMapping.apply(pdeStage); - - // Create AST - syntaxCU = makeAST(parser, syntaxStage.toCharArray(), COMPILER_OPTIONS); - - // Get syntax problems - List syntaxProblems = Arrays.asList(syntaxCU.getProblems()); - - // Update result - result.syntaxMapping = syntaxMapping; - result.compilationUnit = syntaxCU; - result.preprocessedCode = syntaxStage; - result.hasSyntaxErrors = syntaxProblems.stream().anyMatch(IProblem::isError); - List mappedSyntaxProblems = - mapProblems(syntaxProblems, result.tabStarts, result.pdeCode, - result.syntaxMapping); - result.problems.addAll(mappedSyntaxProblems); - }} - - { // Prepare ClassLoader and ClassPath - final URLClassLoader classLoader; - final ClassPath classPath; - final String[] classPathArray; - boolean importsChanged = prevResult == null || prevResult.classPath == null || prevResult.classLoader == null || checkIfImportsChanged(programImports, prevResult.programImports) || checkIfImportsChanged(codeFolderImports, prevResult.codeFolderImports); - if (!importsChanged) { - classLoader = prevResult.classLoader; - classPath = prevResult.classPath; - classPathArray = prevResult.classPathArray; - } else { - classPathArray = prepareCompilerClasspath(programImports, sketch); - - // ClassLoader + if (importsChanged) { + String[] classPathArray = prepareCompilerClasspath(programImports, sketch); URL[] urlArray = Arrays.stream(classPathArray) .map(path -> { try { @@ -428,83 +392,90 @@ public class ErrorCheckerService { }) .filter(url -> url != null) .toArray(URL[]::new); - classLoader = new URLClassLoader(urlArray, null); - // ClassPath - classPath = classPathFactory.createFromPaths(classPathArray); + result.classLoader = new URLClassLoader(urlArray, null); + result.classPath = classPathFactory.createFromPaths(classPathArray); + result.classPathArray = classPathArray; + } else { + result.classLoader = prevResult.classLoader; + result.classPath = prevResult.classPath; + result.classPathArray = prevResult.classPathArray; } + // Transform code + String syntaxStage = syntaxMapping.apply(pdeStage); + + // Create AST + CompilationUnit syntaxCU = + makeAST(parser, syntaxStage.toCharArray(), COMPILER_OPTIONS); + + // Prepare transforms + SourceMapping compilationMapping = new SourceMapping(); + compilationMapping.addAll(SourceUtils.addPublicToTopLevelMethods(syntaxCU)); + compilationMapping.addAll(SourceUtils.replaceColorAndFixFloats(syntaxCU)); + + // Transform code + String javaStage = compilationMapping.apply(syntaxStage); + javaStageChars = javaStage.toCharArray(); + + // Create AST + CompilationUnit compilationCU = + makeASTWithBindings(parser, javaStageChars, COMPILER_OPTIONS, + className, result.classPathArray); + // Update result - result.classPath = classPath; - result.classLoader = classLoader; - result.classPathArray = classPathArray; - } + result.syntaxMapping = syntaxMapping; + result.compilationMapping = compilationMapping; + result.javaCode = javaStage; + result.compilationUnit = compilationCU; - if (!result.hasSyntaxErrors) { + // Get syntax problems + List syntaxProblems = Arrays.asList(compilationCU.getProblems()); - {{ // COMPILATION CHECK + result.hasSyntaxErrors = syntaxProblems.stream().anyMatch(IProblem::isError); + }} - // Prepare transforms - SourceMapping compilationMapping = new SourceMapping(); - compilationMapping.addAll(SourceUtils.addPublicToTopLevelMethods(syntaxCU)); - compilationMapping.addAll(SourceUtils.replaceColorAndFixFloats(syntaxCU)); + {{ // COMPILATION CHECK + // Compile it + List compilationProblems = + compileAndReturnProblems(className, javaStageChars, + COMPILER_OPTIONS, result.classLoader, + result.classPath); - // Transform code - javaStage = compilationMapping.apply(syntaxStage); + // TODO: handle error stuff *after* building PreprocessedSketch + List mappedCompilationProblems = + mapProblems(compilationProblems, result.tabStarts, result.pdeCode, + result.compilationMapping, result.syntaxMapping); - char[] javaStageChars = javaStage.toCharArray(); + if (Preferences.getBoolean(JavaMode.SUGGEST_IMPORTS_PREF)) { + Map> undefinedTypeProblems = mappedCompilationProblems.stream() + // Get only problems with undefined types/names + .filter(p -> { + int id = p.getIProblem().getID(); + return id == IProblem.UndefinedType || id == IProblem.UndefinedName; + }) + // Group problems by the missing type/name + .collect(Collectors.groupingBy(p -> p.getIProblem().getArguments()[0])); - // Create AST - CompilationUnit compilationCU = makeASTWithBindings(parser, javaStageChars, - COMPILER_OPTIONS, - className, result.classPathArray); + // TODO: cache this, invalidate if code folder or libraries change + final ClassPath cp = undefinedTypeProblems.isEmpty() ? + null : + buildImportSuggestionClassPath(); - // Compile it - List compilationProblems = - compileAndReturnProblems(className, javaStageChars, - COMPILER_OPTIONS, result.classLoader, - result.classPath); + // Get suggestions for each missing type, update the problems + undefinedTypeProblems.entrySet().stream() + .forEach(entry -> { + String missingClass = entry.getKey(); + List problems = entry.getValue(); + String[] suggestions = getImportSuggestions(cp, missingClass); + problems.forEach(p -> p.setImportSuggestions(suggestions)); + }); + } - // Update result - result.compilationMapping = compilationMapping; - result.preprocessedCode = javaStage; - result.compilationUnit = compilationCU; + result.problems.addAll(mappedCompilationProblems); - // TODO: handle error stuff *after* building PreprocessedSketch - List mappedCompilationProblems = - mapProblems(compilationProblems, result.tabStarts, result.pdeCode, - result.compilationMapping, result.syntaxMapping); - - if (Preferences.getBoolean(JavaMode.SUGGEST_IMPORTS_PREF)) { - Map> undefinedTypeProblems = mappedCompilationProblems.stream() - // Get only problems with undefined types/names - .filter(p -> { - int id = p.getIProblem().getID(); - return id == IProblem.UndefinedType || id == IProblem.UndefinedName; - }) - // Group problems by the missing type/name - .collect(Collectors.groupingBy(p -> p.getIProblem().getArguments()[0])); - - // TODO: cache this, invalidate if code folder or libraries change - final ClassPath cp = undefinedTypeProblems.isEmpty() ? - null : - buildImportSuggestionClassPath(); - - // Get suggestions for each missing type, update the problems - undefinedTypeProblems.entrySet().stream() - .forEach(entry -> { - String missingClass = entry.getKey(); - List problems = entry.getValue(); - String[] suggestions = getImportSuggestions(cp, missingClass); - problems.forEach(p -> p.setImportSuggestions(suggestions)); - }); - } - - result.problems.addAll(mappedCompilationProblems); - - result.hasCompilationErrors = mappedCompilationProblems.stream() - .anyMatch(Problem::isError); - }} - } + result.hasCompilationErrors = mappedCompilationProblems.stream() + .anyMatch(Problem::isError); + }} return result.build(); } diff --git a/java/src/processing/mode/java/pdex/PreprocessedSketch.java b/java/src/processing/mode/java/pdex/PreprocessedSketch.java index 58bda981d..7c8ab194d 100644 --- a/java/src/processing/mode/java/pdex/PreprocessedSketch.java +++ b/java/src/processing/mode/java/pdex/PreprocessedSketch.java @@ -25,7 +25,7 @@ public class PreprocessedSketch { public final int[] tabStarts; public final String pdeCode; - public final String preprocessedCode; + public final String javaCode; public final SourceMapping syntaxMapping; public final SourceMapping compilationMapping; @@ -85,7 +85,7 @@ public class PreprocessedSketch { if (compilationMapping != null) { javaLineOffset = compilationMapping.getOutputOffset(javaLineOffset); } - return offsetToLine(preprocessedCode, javaLineOffset); + return offsetToLine(javaCode, javaLineOffset); } @@ -155,7 +155,7 @@ public class PreprocessedSketch { public int[] tabStarts = new int[0]; public String pdeCode; - public String preprocessedCode; + public String javaCode; public SourceMapping syntaxMapping; public SourceMapping compilationMapping; @@ -190,7 +190,7 @@ public class PreprocessedSketch { tabStarts = b.tabStarts; pdeCode = b.pdeCode; - preprocessedCode = b.preprocessedCode; + javaCode = b.javaCode; syntaxMapping = b.syntaxMapping; compilationMapping = b.compilationMapping;