7144981: javac should ignore ignorable characters in input

Fri, 23 Nov 2012 15:13:45 +0000

author
vromero
date
Fri, 23 Nov 2012 15:13:45 +0000
changeset 1431
1f41a5758cf7
parent 1430
4d68e2a05b50
child 1432
969c96b980b7

7144981: javac should ignore ignorable characters in input
Reviewed-by: jjg, mcimadamore

src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java file | annotate | diff | comparison | revisions
test/tools/javac/7144981/IgnoreIgnorableCharactersInInput.java file | annotate | diff | comparison | revisions
     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 +}

mercurial