Fri, 23 Nov 2012 15:13:45 +0000
7144981: javac should ignore ignorable characters in input
Reviewed-by: jjg, mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Tue Nov 27 13:55:10 2012 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Fri Nov 23 15:13:45 2012 +0000 1.3 @@ -348,8 +348,8 @@ 1.4 private void scanIdent() { 1.5 boolean isJavaIdentifierPart; 1.6 char high; 1.7 + reader.putChar(true); 1.8 do { 1.9 - reader.putChar(true); 1.10 switch (reader.ch) { 1.11 case 'A': case 'B': case 'C': case 'D': case 'E': 1.12 case 'F': case 'G': case 'H': case 'I': case 'J': 1.13 @@ -366,6 +366,7 @@ 1.14 case '$': case '_': 1.15 case '0': case '1': case '2': case '3': case '4': 1.16 case '5': case '6': case '7': case '8': case '9': 1.17 + break; 1.18 case '\u0000': case '\u0001': case '\u0002': case '\u0003': 1.19 case '\u0004': case '\u0005': case '\u0006': case '\u0007': 1.20 case '\u0008': case '\u000E': case '\u000F': case '\u0010': 1.21 @@ -373,26 +374,33 @@ 1.22 case '\u0015': case '\u0016': case '\u0017': 1.23 case '\u0018': case '\u0019': case '\u001B': 1.24 case '\u007F': 1.25 - break; 1.26 + reader.scanChar(); 1.27 + continue; 1.28 case '\u001A': // EOI is also a legal identifier part 1.29 if (reader.bp >= reader.buflen) { 1.30 name = reader.name(); 1.31 tk = tokens.lookupKind(name); 1.32 return; 1.33 } 1.34 - break; 1.35 + reader.scanChar(); 1.36 + continue; 1.37 default: 1.38 if (reader.ch < '\u0080') { 1.39 // all ASCII range chars already handled, above 1.40 isJavaIdentifierPart = false; 1.41 } else { 1.42 - high = reader.scanSurrogates(); 1.43 - if (high != 0) { 1.44 - reader.putChar(high); 1.45 - isJavaIdentifierPart = Character.isJavaIdentifierPart( 1.46 - Character.toCodePoint(high, reader.ch)); 1.47 + if (Character.isIdentifierIgnorable(reader.ch)) { 1.48 + reader.scanChar(); 1.49 + continue; 1.50 } else { 1.51 - isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); 1.52 + high = reader.scanSurrogates(); 1.53 + if (high != 0) { 1.54 + reader.putChar(high); 1.55 + isJavaIdentifierPart = Character.isJavaIdentifierPart( 1.56 + Character.toCodePoint(high, reader.ch)); 1.57 + } else { 1.58 + isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); 1.59 + } 1.60 } 1.61 } 1.62 if (!isJavaIdentifierPart) { 1.63 @@ -401,6 +409,7 @@ 1.64 return; 1.65 } 1.66 } 1.67 + reader.putChar(true); 1.68 } while (true); 1.69 } 1.70
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/7144981/IgnoreIgnorableCharactersInInput.java Fri Nov 23 15:13:45 2012 +0000 2.3 @@ -0,0 +1,92 @@ 2.4 + 2.5 +/* 2.6 + * @test /nodynamiccopyright/ 2.7 + * @bug 7144981 2.8 + * @summary javac should ignore ignorable characters in input 2.9 + * @run main IgnoreIgnorableCharactersInInput 2.10 + */ 2.11 + 2.12 +import com.sun.source.util.JavacTask; 2.13 +import java.io.File; 2.14 +import java.net.URI; 2.15 +import java.util.Arrays; 2.16 +import java.util.Set; 2.17 +import java.util.TreeSet; 2.18 +import javax.tools.JavaCompiler; 2.19 +import javax.tools.JavaFileObject; 2.20 +import javax.tools.SimpleJavaFileObject; 2.21 +import javax.tools.ToolProvider; 2.22 + 2.23 +public class IgnoreIgnorableCharactersInInput { 2.24 + 2.25 + public static void main(String... args) throws Exception { 2.26 + new IgnoreIgnorableCharactersInInput().run(); 2.27 + } 2.28 + 2.29 + void run() throws Exception { 2.30 + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 2.31 + File classesDir = new File(System.getProperty("user.dir"), "classes"); 2.32 + classesDir.mkdirs(); 2.33 + JavaSource[] sources = new JavaSource[]{ 2.34 + new JavaSource("TestOneIgnorableChar", "AA\\u0000BB"), 2.35 + new JavaSource("TestMultipleIgnorableChar", "AA\\u0000\\u0000\\u0000BB")}; 2.36 + JavacTask ct = (JavacTask)comp.getTask(null, null, null, 2.37 + Arrays.asList("-d", classesDir.getPath()), 2.38 + null, Arrays.asList(sources)); 2.39 + try { 2.40 + if (!ct.call()) { 2.41 + throw new AssertionError("Error thrown when compiling test cases"); 2.42 + } 2.43 + } catch (Throwable ex) { 2.44 + throw new AssertionError("Error thrown when compiling test cases"); 2.45 + } 2.46 + check(classesDir, 2.47 + "TestOneIgnorableChar.class", 2.48 + "TestOneIgnorableChar$AABB.class", 2.49 + "TestMultipleIgnorableChar.class", 2.50 + "TestMultipleIgnorableChar$AABB.class"); 2.51 + if (errors > 0) 2.52 + throw new AssertionError("There are some errors in the test check the error output"); 2.53 + } 2.54 + 2.55 + /** 2.56 + * Check that a directory contains the expected files. 2.57 + */ 2.58 + void check(File dir, String... paths) { 2.59 + Set<String> found = new TreeSet<String>(Arrays.asList(dir.list())); 2.60 + Set<String> expect = new TreeSet<String>(Arrays.asList(paths)); 2.61 + if (found.equals(expect)) 2.62 + return; 2.63 + for (String f: found) { 2.64 + if (!expect.contains(f)) 2.65 + error("Unexpected file found: " + f); 2.66 + } 2.67 + for (String e: expect) { 2.68 + if (!found.contains(e)) 2.69 + error("Expected file not found: " + e); 2.70 + } 2.71 + } 2.72 + 2.73 + int errors; 2.74 + 2.75 + void error(String msg) { 2.76 + System.err.println(msg); 2.77 + errors++; 2.78 + } 2.79 + 2.80 + class JavaSource extends SimpleJavaFileObject { 2.81 + 2.82 + String internalSource = 2.83 + "public class #O {public class #I {} }"; 2.84 + public JavaSource(String outerClassName, String innerClassName) { 2.85 + super(URI.create(outerClassName + ".java"), JavaFileObject.Kind.SOURCE); 2.86 + internalSource = 2.87 + internalSource.replace("#O", outerClassName).replace("#I", innerClassName); 2.88 + } 2.89 + 2.90 + @Override 2.91 + public CharSequence getCharContent(boolean ignoreEncodingErrors) { 2.92 + return internalSource; 2.93 + } 2.94 + } 2.95 +}