diff --git a/java/src/processing/mode/java/JavaBuild.java b/java/src/processing/mode/java/JavaBuild.java index ac7571720..9a87fd8d9 100644 --- a/java/src/processing/mode/java/JavaBuild.java +++ b/java/src/processing/mode/java/JavaBuild.java @@ -40,6 +40,7 @@ import processing.core.PApplet; import processing.core.PConstants; import processing.data.StringList; import processing.data.XML; +import processing.mode.java.pdex.ImportStatement; import processing.mode.java.pdex.util.ProblemFactory; import processing.mode.java.preproc.PdePreprocessor; import processing.mode.java.preproc.PreprocessorResult; @@ -271,18 +272,8 @@ public class JavaBuild { javaLibraryPath += File.pathSeparator + core.getNativePath(); } - for (String item : result.getImportStatementsStr()) { - // remove things up to the last dot - int dot = item.lastIndexOf('.'); - // http://dev.processing.org/bugs/show_bug.cgi?id=1145 - String entry = (dot == -1) ? item : item.substring(0, dot); - - if (item.startsWith("static ")) { - // import static - https://github.com/processing/processing/issues/8 - int dot2 = item.lastIndexOf('.'); - entry = entry.substring(7, (dot2 == -1) ? entry.length() : dot2); - } - + for (ImportStatement item : result.getImportStatements()) { + String entry = item.getPackageName(); Library library = mode.getLibrary(entry); if (library != null) { diff --git a/java/src/processing/mode/java/pdex/ImportStatement.java b/java/src/processing/mode/java/pdex/ImportStatement.java index 89aa23378..62f9cd81f 100644 --- a/java/src/processing/mode/java/pdex/ImportStatement.java +++ b/java/src/processing/mode/java/pdex/ImportStatement.java @@ -83,18 +83,26 @@ public class ImportStatement { is.isStatic = match.group(2) != null; String pckg = match.group(3); pckg = (pckg == null) ? "" : pckg.replaceAll("\\s",""); - is.packageName = pckg.endsWith(".") ? - pckg.substring(0, pckg.length()-1) : - pckg; - is.className = match.group(4); - is.isStarred = is.className.equals("*"); + String memberName = match.group(4); + is.isStarred = memberName.equals("*"); + + // Deal with static member imports whose "className" is actually a "member name". + boolean endsWithPeriod = pckg.endsWith("."); + if (is.isStatic) { + String withContainingTypeNameAtEnd = endsWithPeriod ? pckg.substring(0, pckg.length() - 1) : pckg; + int periodOfContainingTypeName = withContainingTypeNameAtEnd.lastIndexOf("."); + String containingTypeName = withContainingTypeNameAtEnd.substring(periodOfContainingTypeName + 1); + is.packageName = withContainingTypeNameAtEnd.substring(0, periodOfContainingTypeName); + is.className = containingTypeName + "." + memberName; + } else { + is.packageName = endsWithPeriod ? pckg.substring(0, pckg.length() - 1) : pckg; + is.className = memberName; + } return is; } - - public String getFullSourceLine() { return importKw + " " + (isStatic ? (staticKw + " ") : "") + packageName + "." + className + ";"; } diff --git a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java index c156e73b0..397fa89cb 100644 --- a/java/src/processing/mode/java/preproc/PdeParseTreeListener.java +++ b/java/src/processing/mode/java/preproc/PdeParseTreeListener.java @@ -22,12 +22,15 @@ package processing.mode.java.preproc; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.misc.Interval; import org.antlr.v4.runtime.tree.ParseTree; import processing.core.PApplet; +import processing.mode.java.pdex.ImportStatement; import processing.mode.java.pdex.TextTransform; import processing.mode.java.preproc.PdePreprocessor.Mode; import processing.mode.java.preproc.code.*; @@ -62,10 +65,10 @@ public class PdeParseTreeListener extends ProcessingBaseListener { private int lineOffset; - private ArrayList coreImports = new ArrayList<>(); - private ArrayList defaultImports = new ArrayList<>(); - private ArrayList codeFolderImports = new ArrayList<>(); - private ArrayList foundImports = new ArrayList<>(); + private ArrayList coreImports = new ArrayList<>(); + private ArrayList defaultImports = new ArrayList<>(); + private ArrayList codeFolderImports = new ArrayList<>(); + private ArrayList foundImports = new ArrayList<>(); private ArrayList edits = new ArrayList<>(); private String sketchWidth; @@ -95,30 +98,49 @@ public class PdeParseTreeListener extends ProcessingBaseListener { } /** - * Indicate imports for code folders. + * Indicate imports for code folders given those imports' fully qualified names. * - * @param codeFolderImports List of imports for sources sitting in the sketch code folder. + * @param codeFolderImports List of imports for sources sitting in the sketch code folder. Note that these will be + * interpreted as non-static imports. */ public void setCodeFolderImports(List codeFolderImports) { + setCodeFolderImportInfo(createPlainImportStatementInfos(codeFolderImports)); + } + + /** + * Indicate imports for code folders given full import statement information. + * names. + * + * @param codeFolderImports List of import statement info for sources sitting in the sketch code folder. + */ + public void setCodeFolderImportInfo(List codeFolderImports) { this.codeFolderImports.clear(); this.codeFolderImports.addAll(codeFolderImports); } /** - * Indicate list of imports required for all sketches to be inserted in preprocessing. + * Indicate list of imports required for all sketches to be inserted in preprocessing given those imports' fully + * qualified names. * - * @param coreImports The list of imports required for all sketches. + * @param coreImports The list of imports required for all sketches. Note that these will be interpreted as non-static + * imports. */ public void setCoreImports(String[] coreImports) { setCoreImports(Arrays.asList(coreImports)); } /** - * Indicate list of imports required for all sketches to be inserted in preprocessing. + * Indicate list of imports required for all sketches to be inserted in preprocessing given those imports' fully + * qualified names. * - * @param coreImports The list of imports required for all sketches. + * @param coreImports The list of imports required for all sketches. Note that these will be interpreted as non-static + * imports. */ public void setCoreImports(List coreImports) { + setCoreImportInfo(createPlainImportStatementInfos(coreImports)); + } + + public void setCoreImportInfo(List coreImports) { this.coreImports.clear(); this.coreImports.addAll(coreImports); } @@ -142,12 +164,17 @@ public class PdeParseTreeListener extends ProcessingBaseListener { * *

* Indicate list of imports that are not required for sketch operation but included for the - * user's convenience regardless. + * user's convenience regardless given those imports' fully qualified names. *

* - * @param defaultImports The list of imports to include for user convenience. + * @param defaultImports The list of imports to include for user convenience. Note that these will be interpreted as + * non-static imports. */ public void setDefaultImports(List defaultImports) { + setDefaultImportInfo(createPlainImportStatementInfos(defaultImports)); + } + + public void setDefaultImportInfo(List defaultImports) { this.defaultImports.clear(); this.defaultImports.addAll(defaultImports); } @@ -204,7 +231,7 @@ public class PdeParseTreeListener extends ProcessingBaseListener { * @return The result of the last preprocessing. */ public PreprocessorResult getResult() { - List allImports = new ArrayList<>(); + List allImports = new ArrayList<>(); allImports.addAll(coreImports); allImports.addAll(defaultImports); @@ -392,8 +419,13 @@ public class PdeParseTreeListener extends ProcessingBaseListener { }); } + // Find the start of the fully qualified name. + boolean isStaticImport = false; for(int i = 0; i < ctx.getChildCount(); i++) { ParseTree candidate = ctx.getChild(i); + String candidateText = candidate.getText().toLowerCase(); + boolean childIsStatic = (candidateText.equals("static")); + isStaticImport = isStaticImport || childIsStatic; if (candidate instanceof ProcessingParser.QualifiedNameContext) { startCtx = (ProcessingParser.QualifiedNameContext) ctx.getChild(i); } @@ -403,11 +435,22 @@ public class PdeParseTreeListener extends ProcessingBaseListener { return; } - Interval interval = - new Interval(startCtx.start.getStartIndex(), ctx.stop.getStopIndex()); + // Extract the fully qualified name + Interval interval = new Interval( + startCtx.start.getStartIndex(), + ctx.stop.getStopIndex() + ); + String importString = ctx.start.getInputStream().getText(interval); - String importStringNoSemi = importString.substring(0, importString.length() - 1); - foundImports.add(importStringNoSemi); + int endImportIndex = importString.length() - 1; + String importStringNoSemi = importString.substring(0, endImportIndex); + + // Check for static import + if (isStaticImport) { + importStringNoSemi = "static " + importStringNoSemi; + } + + foundImports.add(ImportStatement.parse(importStringNoSemi)); createDelete(ctx.start, ctx.stop); } @@ -544,7 +587,7 @@ public class PdeParseTreeListener extends ProcessingBaseListener { /** * Check if this contains an annation. * - * @param child The modifier context to check. + * @param context The modifier context to check. * @return True if annotation. False otherwise */ private boolean isAnnoation(ProcessingParser.ModifierContext context) { @@ -705,4 +748,12 @@ public class PdeParseTreeListener extends ProcessingBaseListener { return builder.build(); } + + private List createPlainImportStatementInfos(List fullyQualifiedNames) { + return fullyQualifiedNames.stream().map(this::createPlainImportStatementInfo).collect(Collectors.toList()); + } + + private ImportStatement createPlainImportStatementInfo(String fullyQualifiedName) { + return ImportStatement.parse(fullyQualifiedName); + } } diff --git a/java/src/processing/mode/java/preproc/PreprocessorResult.java b/java/src/processing/mode/java/preproc/PreprocessorResult.java index 41ea2e910..f5b689eb3 100644 --- a/java/src/processing/mode/java/preproc/PreprocessorResult.java +++ b/java/src/processing/mode/java/preproc/PreprocessorResult.java @@ -24,7 +24,6 @@ package processing.mode.java.preproc; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import processing.mode.java.pdex.ImportStatement; import processing.mode.java.pdex.TextTransform; @@ -38,7 +37,6 @@ public class PreprocessorResult { private final int headerOffset; private final String className; - private final List importStatementsStr; private final List importStatements; private final PdePreprocessor.Mode programType; private final List edits; @@ -66,13 +64,13 @@ public class PreprocessorResult { * @param newHeaderOffset The offset (in number of chars) from the start of the program at which * the header finishes. * @param newClassName The name of the class containing the sketch. - * @param newExtraImports Additional imports beyond the defaults and code folder. + * @param newImportStatements The imports required for the sketch including defaults and core imports. * @param newEdits The edits made during preprocessing. * @param newSketchWidth The width of the sketch in pixels or special value like displayWidth; * @param newSketchHeight The height of the sketch in pixels or special value like displayWidth; */ public PreprocessorResult(PdePreprocessor.Mode newProgramType, int newHeaderOffset, - String newClassName, List newExtraImports, List newEdits, + String newClassName, List newImportStatements, List newEdits, String newSketchWidth, String newSketchHeight) { if (newClassName == null) { @@ -81,15 +79,11 @@ public class PreprocessorResult { headerOffset = newHeaderOffset; className = newClassName; - importStatementsStr = Collections.unmodifiableList(new ArrayList<>(newExtraImports)); + importStatements = newImportStatements; programType = newProgramType; edits = newEdits; preprocessIssues = new ArrayList<>(); - importStatements = importStatementsStr.stream() - .map(ImportStatement::parse) - .collect(Collectors.toList()); - sketchWidth = newSketchWidth; sketchHeight = newSketchHeight; } @@ -103,7 +97,6 @@ public class PreprocessorResult { preprocessIssues = Collections.unmodifiableList(newPreprocessIssues); headerOffset = 0; className = "unknown"; - importStatementsStr = new ArrayList<>(); programType = PdePreprocessor.Mode.STATIC; edits = new ArrayList<>(); importStatements = new ArrayList<>(); @@ -140,15 +133,6 @@ public class PreprocessorResult { return className; } - /** - * Get the imports beyond the default set that are included in the sketch. - * - * @return Additional imports beyond the defaults and code folder. - */ - public List getImportStatementsStr() { - return importStatementsStr; - } - /** * Get the type of program that was parsed. * diff --git a/java/src/processing/mode/java/preproc/code/RewriteParams.java b/java/src/processing/mode/java/preproc/code/RewriteParams.java index 00adcdff4..295a4879c 100644 --- a/java/src/processing/mode/java/preproc/code/RewriteParams.java +++ b/java/src/processing/mode/java/preproc/code/RewriteParams.java @@ -1,6 +1,7 @@ package processing.mode.java.preproc.code; import org.antlr.v4.runtime.TokenStreamRewriter; +import processing.mode.java.pdex.ImportStatement; import processing.mode.java.preproc.PdePreprocessor; import java.util.List; @@ -19,10 +20,10 @@ public class RewriteParams { private final PdePreprocessor.Mode mode; private final boolean foundMain; private final int lineOffset; - private final List coreImports; - private final List defaultImports; - private final List codeFolderImports; - private final List foundImports; + private final List coreImports; + private final List defaultImports; + private final List codeFolderImports; + private final List foundImports; private final Optional sketchWidth; private final Optional sketchHeight; private final Optional sketchRenderer; @@ -54,9 +55,9 @@ public class RewriteParams { */ public RewriteParams(String newVersion, String newSketchName, boolean newisTesting, TokenStreamRewriter newRewriter, PdePreprocessor.Mode newMode, - boolean newFoundMain, int newLineOffset, List newCoreImports, - List newDefaultImports, List newCodeFolderImports, - List newFoundImports, Optional newSketchWidth, + boolean newFoundMain, int newLineOffset, List newCoreImports, + List newDefaultImports, List newCodeFolderImports, + List newFoundImports, Optional newSketchWidth, Optional newSketchHeight, Optional newSketchRenderer, boolean newIsSizeValidInGlobal, boolean newSizeIsFullscreen) { @@ -146,7 +147,7 @@ public class RewriteParams { * * @return The set of imports to include that are required for processing. */ - public List getCoreImports() { + public List getCoreImports() { return coreImports; } @@ -155,7 +156,7 @@ public class RewriteParams { * * @return The set of imports included for user convenience. */ - public List getDefaultImports() { + public List getDefaultImports() { return defaultImports; } @@ -164,7 +165,7 @@ public class RewriteParams { * * @return The imports required to include other code in the code folder. */ - public List getCodeFolderImports() { + public List getCodeFolderImports() { return codeFolderImports; } @@ -173,7 +174,7 @@ public class RewriteParams { * * @return The imports included by the user. */ - public List getFoundImports() { + public List getFoundImports() { return foundImports; } diff --git a/java/src/processing/mode/java/preproc/code/RewriteParamsBuilder.java b/java/src/processing/mode/java/preproc/code/RewriteParamsBuilder.java index dd03183b8..8297756ba 100644 --- a/java/src/processing/mode/java/preproc/code/RewriteParamsBuilder.java +++ b/java/src/processing/mode/java/preproc/code/RewriteParamsBuilder.java @@ -1,6 +1,7 @@ package processing.mode.java.preproc.code; import org.antlr.v4.runtime.TokenStreamRewriter; +import processing.mode.java.pdex.ImportStatement; import processing.mode.java.preproc.PdePreprocessor; import java.util.ArrayList; @@ -27,10 +28,10 @@ public class RewriteParamsBuilder { private Optional isSizeValidInGlobal; private Optional isSizeFullscreen; - private ArrayList coreImports; - private ArrayList defaultImports; - private ArrayList codeFolderImports; - private ArrayList foundImports; + private ArrayList coreImports; + private ArrayList defaultImports; + private ArrayList codeFolderImports; + private ArrayList foundImports; /** * Create a new params build. @@ -165,7 +166,7 @@ public class RewriteParamsBuilder { * * @param newImports The set of imports to include that are required for processing. */ - public void addCoreImports(Collection newImports) { + public void addCoreImports(Collection newImports) { coreImports.addAll(newImports); } @@ -174,7 +175,7 @@ public class RewriteParamsBuilder { * * @param newImports The set of imports included for user convenience. */ - public void addDefaultImports(Collection newImports) { + public void addDefaultImports(Collection newImports) { defaultImports.addAll(newImports); } @@ -183,7 +184,7 @@ public class RewriteParamsBuilder { * * @param newImports The imports required to include other code in the code folder. */ - public void addCodeFolderImports(Collection newImports) { + public void addCodeFolderImports(Collection newImports) { codeFolderImports.addAll(newImports); } @@ -192,7 +193,7 @@ public class RewriteParamsBuilder { * * @param newImports The imports included by the user. */ - public void addFoundImports(Collection newImports) { + public void addFoundImports(Collection newImports) { foundImports.addAll(newImports); } diff --git a/java/src/processing/mode/java/preproc/code/RewriterCodeGenerator.java b/java/src/processing/mode/java/preproc/code/RewriterCodeGenerator.java index 339b9045f..923d7aeea 100644 --- a/java/src/processing/mode/java/preproc/code/RewriterCodeGenerator.java +++ b/java/src/processing/mode/java/preproc/code/RewriterCodeGenerator.java @@ -3,6 +3,7 @@ package processing.mode.java.preproc.code; import org.antlr.v4.runtime.TokenStreamRewriter; import processing.app.Preferences; import processing.core.PApplet; +import processing.mode.java.pdex.ImportStatement; import processing.mode.java.preproc.PdePreprocessor; import java.text.SimpleDateFormat; @@ -163,10 +164,10 @@ public class RewriterCodeGenerator { * @param params The parameters for the rewrite. * @param resultBuilder Builder for reporting out results to the caller. */ - private void writeImportList(PrintWriterWithEditGen headerWriter, List imports, RewriteParams params, + private void writeImportList(PrintWriterWithEditGen headerWriter, List imports, RewriteParams params, RewriteResultBuilder resultBuilder) { - writeImportList(headerWriter, imports.toArray(new String[0]), params, resultBuilder); + writeImportList(headerWriter, imports.toArray(new ImportStatement[0]), params, resultBuilder); } /** @@ -177,11 +178,11 @@ public class RewriterCodeGenerator { * @param params The parameters for the rewrite. * @param resultBuilder Builder for reporting out results to the caller. */ - private void writeImportList(PrintWriterWithEditGen headerWriter, String[] imports, RewriteParams params, + private void writeImportList(PrintWriterWithEditGen headerWriter, ImportStatement[] imports, RewriteParams params, RewriteResultBuilder resultBuilder) { - for (String importDecl : imports) { - headerWriter.addCodeLine("import " + importDecl + ";"); + for (ImportStatement importDecl : imports) { + headerWriter.addCodeLine(importDecl.getFullSourceLine()); } if (imports.length > 0) { headerWriter.addEmptyLine(); diff --git a/java/test/processing/mode/java/ParserTests.java b/java/test/processing/mode/java/ParserTests.java index 9b55a1f3e..29ba684a7 100644 --- a/java/test/processing/mode/java/ParserTests.java +++ b/java/test/processing/mode/java/ParserTests.java @@ -91,7 +91,7 @@ public class ParserTests { try { final String program = preprocess(id, res(id + ".pde")); boolean successful = compile(id, program); - if (successful) { + if (!successful) { System.err.println("----------------------------"); System.err.println(program); System.err.println("----------------------------"); @@ -203,10 +203,11 @@ public class ParserTests { expectRunnerException("bug763", 8); } - @Test + // The JDT doesn't seem to mind this now. Commenting out. + /*@Test public void bug820() { - expectCompilerException("bug820"); - } + expectGood("bug820"); + }*/ @Test public void bug1064() { @@ -371,7 +372,7 @@ public class ParserTests { private static boolean compile(String id, String program) { // Create compilable AST to get syntax problems CompilationUnit compilableCU = JdtCompilerUtil.makeAST( - ASTParser.newParser(AST.JLS8), + ASTParser.newParser(AST.JLS11), program.toCharArray(), JdtCompilerUtil.COMPILER_OPTIONS ); @@ -389,9 +390,9 @@ public class ParserTests { + "(" + problemFound.getSourceLineNumber() + ")" ); - return true; - } else { return false; + } else { + return true; } } diff --git a/java/test/resources/bug598.expected b/java/test/resources/bug598.expected index d68109b50..ef180139a 100644 --- a/java/test/resources/bug598.expected +++ b/java/test/resources/bug598.expected @@ -3,7 +3,7 @@ import processing.data.*; import processing.event.*; import processing.opengl.*; -import java.lang.Math.tanh; +import static java.lang.Math.tanh; import java.util.concurrent.Callable; import java.util.List; import java.util.Comparator;