--- old/src/share/classes/sun/reflect/generics/parser/SignatureParser.java 2011-09-02 08:45:18.000000000 -0700
+++ new/src/share/classes/sun/reflect/generics/parser/SignatureParser.java 2011-09-02 08:45:18.000000000 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,15 @@
package sun.reflect.generics.parser;
-
import java.lang.reflect.GenericSignatureFormatError;
import java.util.*;
import sun.reflect.generics.tree.*;
-
/**
* Parser for type signatures, as defined in the Java Virtual
-// Machine Specification (JVMS) chapter 4.
+ * Machine Specification (JVMS) chapter 4.
* Converts the signatures into an abstract syntax tree (AST) representation.
-// See the package sun.reflect.generics.tree for details of the AST.
+ * See the package sun.reflect.generics.tree for details of the AST.
*/
public class SignatureParser {
// The input is conceptually a character stream (though currently it's
@@ -58,8 +56,8 @@
// if (current != x {error("expected an x");
//
// where x is some character constant.
- // The assertion inidcates, that, as currently written,
- // the code should nver reach this point unless the input is an
+ // The assertion indicates, that, as currently written,
+ // the code should never reach this point unless the input is an
// x. On the other hand, the test is there to check the legality
// of the input wrt to a given production. It may be that at a later
// time the code might be called directly, and if the input is
@@ -68,7 +66,7 @@
private char[] input; // the input signature
private int index = 0; // index into the input
-// used to mark end of input
+ // used to mark end of input
private static final char EOI = ':';
private static final boolean DEBUG = false;
@@ -104,6 +102,11 @@
index++;
}
+ // For debugging, prints current character to the end of the input.
+ private String remainder() {
+ return new String(input, index, input.length-index);
+ }
+
// Match c against a "set" of characters
private boolean matches(char c, char... set) {
for (char e : set) {
@@ -117,11 +120,22 @@
// Currently throws a GenericSignatureFormatError.
private Error error(String errorMsg) {
- if (DEBUG) System.out.println("Parse error:" + errorMsg);
+ if (DEBUG)
+ System.out.println("Signature Parse error: " + errorMsg +
+ "\n\tRemaining input: " + remainder());
return new GenericSignatureFormatError();
}
/**
+ * Verify the parse has made forward progress; throw an exception
+ * if no progress.
+ */
+ private void progress(int startingPosition) {
+ if (index <= startingPosition)
+ throw error("Failure to make progress!");
+ }
+
+ /**
* Static factory method. Produces a parser instance.
* @return an instance of SignatureParser
*/
@@ -163,6 +177,7 @@
/**
* Parses a type signature
* and produces an abstract syntax tree representing it.
+ *
* @param s a string representing the input type signature
* @return An abstract syntax tree for a type signature
* corresponding to the input string
@@ -183,38 +198,58 @@
// and when it completes parsing, it leaves the input at the first
// character after the input parses.
- // parse a class signature based on the implicit input.
+ /*
+ * Note on grammar conventions: a trailing "*" matches zero or
+ * more occurrences, a trailing "+" matches one or more occurrences,
+ * "_opt" indicates an optional component.
+ */
+
+ /**
+ * ClassSignature:
+ * FormalTypeParameters_opt SuperclassSignature SuperinterfaceSignature*
+ */
private ClassSignature parseClassSignature() {
+ // parse a class signature based on the implicit input.
assert(index == 0);
return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
- parseClassTypeSignature(),
+ parseClassTypeSignature(), // Only rule for SuperclassSignature
parseSuperInterfaces());
}
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
- if (current() == '<') { return parseFormalTypeParameters();}
- else {return new FormalTypeParameter[0];}
+ if (current() == '<') {
+ return parseFormalTypeParameters();
+ } else {
+ return new FormalTypeParameter[0];
+ }
}
-
+ /**
+ * FormalTypeParameters:
+ * "<" FormalTypeParameter+ ">"
+ */
private FormalTypeParameter[] parseFormalTypeParameters(){
- Collection ftps =
- new ArrayList(3);
+ List ftps = new ArrayList<>(3);
assert(current() == '<'); // should not have been called at all
- if (current() != '<') { throw error("expected <");}
+ if (current() != '<') { throw error("expected '<'");}
advance();
ftps.add(parseFormalTypeParameter());
while (current() != '>') {
+ int startingPosition = index;
ftps.add(parseFormalTypeParameter());
+ progress(startingPosition);
}
advance();
- FormalTypeParameter[] ftpa = new FormalTypeParameter[ftps.size()];
- return ftps.toArray(ftpa);
+ return ftps.toArray(new FormalTypeParameter[ftps.size()]);
}
+ /**
+ * FormalTypeParameter:
+ * Identifier ClassBound InterfaceBound*
+ */
private FormalTypeParameter parseFormalTypeParameter(){
String id = parseIdentifier();
- FieldTypeSignature[] bs = parseZeroOrMoreBounds();
+ FieldTypeSignature[] bs = parseBounds();
return FormalTypeParameter.make(id, bs);
}
@@ -229,7 +264,8 @@
case '[':
case ':':
case '>':
- case '<': return result.toString();
+ case '<':
+ return result.toString();
default:{
result.append(c);
advance();
@@ -239,26 +275,42 @@
}
return result.toString();
}
-
+ /**
+ * FieldTypeSignature:
+ * ClassTypeSignature
+ * ArrayTypeSignature
+ * TypeVariableSignature
+ */
private FieldTypeSignature parseFieldTypeSignature() {
+ return parseFieldTypeSignature(true);
+ }
+
+ private FieldTypeSignature parseFieldTypeSignature(boolean allowArrays) {
switch(current()) {
case 'L':
return parseClassTypeSignature();
case 'T':
return parseTypeVariableSignature();
case '[':
- return parseArrayTypeSignature();
+ if (allowArrays)
+ return parseArrayTypeSignature();
+ else
+ throw error("Array signature not allowed here.");
default: throw error("Expected Field Type Signature");
}
}
+ /**
+ * ClassTypeSignature:
+ * "L" PackageSpecifier_opt SimpleClassTypeSignature ClassTypeSignatureSuffix* ";"
+ */
private ClassTypeSignature parseClassTypeSignature(){
assert(current() == 'L');
if (current() != 'L') { throw error("expected a class type");}
advance();
- List scts =
- new ArrayList(5);
- scts.add(parseSimpleClassTypeSignature(false));
+ List scts = new ArrayList<>(5);
+ scts.add(parsePackageNameAndSimpleClassTypeSignature());
+
parseClassTypeSignatureSuffix(scts);
if (current() != ';')
throw error("expected ';' got '" + current() + "'");
@@ -267,25 +319,65 @@
return ClassTypeSignature.make(scts);
}
- private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
- String id = parseIdentifier();
- char c = current();
- switch (c) {
- case ';':
- case '/':
- return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
- case '<': {
- return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
- }
- default: {throw error("expected < or ; or /");}
+ /**
+ * PackageSpecifier:
+ * Identifier "/" PackageSpecifier*
+ */
+ private SimpleClassTypeSignature parsePackageNameAndSimpleClassTypeSignature() {
+ // Parse both any optional leading PackageSpecifier as well as
+ // the following SimpleClassTypeSignature.
+
+ String id = parseIdentifier();
+
+ if (current() == '/') { // package name
+ StringBuilder idBuild = new StringBuilder(id);
+
+ while(current() == '/') {
+ advance();
+ idBuild.append(".");
+ idBuild.append(parseIdentifier());
}
+ id = idBuild.toString();
+ }
+
+ switch (current()) {
+ case ';':
+ return SimpleClassTypeSignature.make(id, false, new TypeArgument[0]); // all done!
+ case '<':
+ if (DEBUG) System.out.println("\t remainder: " + remainder());
+ return SimpleClassTypeSignature.make(id, false, parseTypeArguments());
+ default:
+ throw error("expected '<' or ';' but got " + current());
+ }
}
+ /**
+ * SimpleClassTypeSignature:
+ * Identifier TypeArguments_opt
+ */
+ private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
+ String id = parseIdentifier();
+ char c = current();
+
+ switch (c) {
+ case ';':
+ case '.':
+ return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
+ case '<':
+ return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
+ default:
+ throw error("expected '<' or ';' or '.', got '" + c + "'.");
+ }
+ }
+
+ /**
+ * ClassTypeSignatureSuffix:
+ * "." SimpleClassTypeSignature
+ */
private void parseClassTypeSignatureSuffix(List scts) {
- while (current() == '/' || current() == '.') {
- boolean dollar = (current() == '.');
+ while (current() == '.') {
advance();
- scts.add(parseSimpleClassTypeSignature(dollar));
+ scts.add(parseSimpleClassTypeSignature(true));
}
}
@@ -294,10 +386,14 @@
else {return new TypeArgument[0];}
}
+ /**
+ * TypeArguments:
+ * "<" TypeArgument+ ">"
+ */
private TypeArgument[] parseTypeArguments() {
- Collection tas = new ArrayList(3);
+ List tas = new ArrayList<>(3);
assert(current() == '<');
- if (current() != '<') { throw error("expected <");}
+ if (current() != '<') { throw error("expected '<'");}
advance();
tas.add(parseTypeArgument());
while (current() != '>') {
@@ -305,10 +401,14 @@
tas.add(parseTypeArgument());
}
advance();
- TypeArgument[] taa = new TypeArgument[tas.size()];
- return tas.toArray(taa);
+ return tas.toArray(new TypeArgument[tas.size()]);
}
+ /**
+ * TypeArgument:
+ * WildcardIndicator_opt FieldTypeSignature
+ * "*"
+ */
private TypeArgument parseTypeArgument() {
FieldTypeSignature[] ub, lb;
ub = new FieldTypeSignature[1];
@@ -334,18 +434,20 @@
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
return Wildcard.make(ub, lb);
}
- default: return parseFieldTypeSignature();
+ default:
+ return parseFieldTypeSignature();
}
}
- // TypeVariableSignature -> T identifier
-
- private TypeVariableSignature parseTypeVariableSignature(){
+ /**
+ * TypeVariableSignature:
+ * "T" Identifier ";"
+ */
+ private TypeVariableSignature parseTypeVariableSignature() {
assert(current() == 'T');
if (current() != 'T') { throw error("expected a type variable usage");}
advance();
- TypeVariableSignature ts =
- TypeVariableSignature.make(parseIdentifier());
+ TypeVariableSignature ts = TypeVariableSignature.make(parseIdentifier());
if (current() != ';') {
throw error("; expected in signature of type variable named" +
ts.getIdentifier());
@@ -354,16 +456,21 @@
return ts;
}
- // ArrayTypeSignature -> [ TypeSignature
-
+ /**
+ * ArrayTypeSignature:
+ * "[" TypeSignature
+ */
private ArrayTypeSignature parseArrayTypeSignature() {
if (current() != '[') {throw error("expected array type signature");}
advance();
return ArrayTypeSignature.make(parseTypeSignature());
}
- // TypeSignature -> BaseType | FieldTypeSignature
-
+ /**
+ * TypeSignature:
+ * FieldTypeSignature
+ * BaseType
+ */
private TypeSignature parseTypeSignature() {
switch (current()) {
case 'B':
@@ -373,8 +480,11 @@
case 'I':
case 'J':
case 'S':
- case 'Z':return parseBaseType();
- default: return parseFieldTypeSignature();
+ case 'Z':
+ return parseBaseType();
+
+ default:
+ return parseFieldTypeSignature();
}
}
@@ -408,12 +518,18 @@
assert(false);
throw error("expected primitive type");
}
- }
+ }
}
- private FieldTypeSignature[] parseZeroOrMoreBounds() {
- Collection fts =
- new ArrayList(3);
+ /**
+ * ClassBound:
+ * ":" FieldTypeSignature_opt
+ *
+ * InterfaceBound:
+ * ":" FieldTypeSignature
+ */
+ private FieldTypeSignature[] parseBounds() {
+ List fts = new ArrayList<>(3);
if (current() == ':') {
advance();
@@ -430,24 +546,31 @@
advance();
fts.add(parseFieldTypeSignature());
}
- }
+ } else
+ error("Bound expected");
- FieldTypeSignature[] fta = new FieldTypeSignature[fts.size()];
- return fts.toArray(fta);
+ return fts.toArray(new FieldTypeSignature[fts.size()]);
}
+ /**
+ * SuperclassSignature:
+ * ClassTypeSignature
+ */
private ClassTypeSignature[] parseSuperInterfaces() {
- Collection cts =
- new ArrayList(5);
+ List cts = new ArrayList<>(5);
while(current() == 'L') {
cts.add(parseClassTypeSignature());
}
- ClassTypeSignature[] cta = new ClassTypeSignature[cts.size()];
- return cts.toArray(cta);
+ return cts.toArray(new ClassTypeSignature[cts.size()]);
}
- // parse a method signature based on the implicit input.
+
+ /**
+ * MethodTypeSignature:
+ * FormalTypeParameters_opt "(" TypeSignature* ")" ReturnType ThrowsSignature*
+ */
private MethodTypeSignature parseMethodTypeSignature() {
+ // Parse a method signature based on the implicit input.
FieldTypeSignature[] ets;
assert(index == 0);
@@ -457,19 +580,19 @@
parseZeroOrMoreThrowsSignatures());
}
- // (TypeSignature*)
+ // "(" TypeSignature* ")"
private TypeSignature[] parseFormalParameters() {
- if (current() != '(') {throw error("expected (");}
+ if (current() != '(') {throw error("expected '('");}
advance();
TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
- if (current() != ')') {throw error("expected )");}
+ if (current() != ')') {throw error("expected ')'");}
advance();
return pts;
}
- // TypeSignature*
+ // TypeSignature*
private TypeSignature[] parseZeroOrMoreTypeSignatures() {
- Collection ts = new ArrayList();
+ List ts = new ArrayList<>();
boolean stop = false;
while (!stop) {
switch(current()) {
@@ -484,47 +607,46 @@
case 'L':
case 'T':
case '[': {
- ts.add(parseTypeSignature());
- break;
- }
+ ts.add(parseTypeSignature());
+ break;
+ }
default: stop = true;
}
}
- /* while( matches(current(),
- 'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 'L', 'T', '[')
- ) {
- ts.add(parseTypeSignature());
- }*/
- TypeSignature[] ta = new TypeSignature[ts.size()];
- return ts.toArray(ta);
+ return ts.toArray(new TypeSignature[ts.size()]);
}
- // ReturnType -> V | TypeSignature
-
+ /**
+ * ReturnType:
+ * TypeSignature
+ * VoidDescriptor
+ */
private ReturnType parseReturnType(){
- if (current() == 'V') {
+ if (current() == 'V') {
advance();
return VoidDescriptor.make();
- } else return parseTypeSignature();
+ } else
+ return parseTypeSignature();
}
// ThrowSignature*
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
- Collection ets =
- new ArrayList(3);
+ List ets = new ArrayList<>(3);
while( current() == '^') {
ets.add(parseThrowsSignature());
}
- FieldTypeSignature[] eta = new FieldTypeSignature[ets.size()];
- return ets.toArray(eta);
+ return ets.toArray(new FieldTypeSignature[ets.size()]);
}
- // ThrowSignature -> ^ FieldTypeSignature
-
+ /**
+ * ThrowsSignature:
+ * "^" ClassTypeSignature
+ * "^" TypeVariableSignature
+ */
private FieldTypeSignature parseThrowsSignature() {
assert(current() == '^');
if (current() != '^') { throw error("expected throws signature");}
advance();
- return parseFieldTypeSignature();
+ return parseFieldTypeSignature(false);
}
}
--- old/test/java/lang/reflect/Generics/Probe.java 2011-09-02 08:45:19.000000000 -0700
+++ new/test/java/lang/reflect/Generics/Probe.java 2011-09-02 08:45:19.000000000 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 5003916 6704655 6873951
+ * @bug 5003916 6704655 6873951 6476261
* @summary Testing parsing of signatures attributes of nested classes
* @author Joseph D. Darcy
*/
@@ -38,12 +38,12 @@
"java.util.concurrent.ConcurrentHashMap$KeyIterator",
"java.util.concurrent.ConcurrentHashMap$ValueIterator",
"java.util.AbstractList$ListItr",
-// "java.util.EnumMap$EntryIterator",
-// "java.util.EnumMap$KeyIterator",
-// "java.util.EnumMap$ValueIterator",
-// "java.util.IdentityHashMap$EntryIterator",
-// "java.util.IdentityHashMap$KeyIterator",
-// "java.util.IdentityHashMap$ValueIterator",
+ "java.util.EnumMap$EntryIterator",
+ "java.util.EnumMap$KeyIterator",
+ "java.util.EnumMap$ValueIterator",
+ "java.util.IdentityHashMap$EntryIterator",
+ "java.util.IdentityHashMap$KeyIterator",
+ "java.util.IdentityHashMap$ValueIterator",
"java.util.WeakHashMap$EntryIterator",
"java.util.WeakHashMap$KeyIterator",
"java.util.WeakHashMap$ValueIterator",
@@ -52,12 +52,12 @@
"java.util.HashMap$ValueIterator",
"java.util.LinkedHashMap$EntryIterator",
"java.util.LinkedHashMap$KeyIterator",
- "java.util.LinkedHashMap$ValueIterator"})
+ "java.util.LinkedHashMap$ValueIterator",
+ "javax.swing.JComboBox$AccessibleJComboBox"})
public class Probe {
public static void main (String... args) throws Throwable {
Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class);
- List names =
- new ArrayList(asList(classesAnnotation.value()));
+ List names = new ArrayList<>(asList(classesAnnotation.value()));
int errs = 0;
for(String name: names) {
--- /dev/null 2011-09-01 02:03:34.128260089 -0700
+++ new/test/java/lang/reflect/Generics/SignatureTest.java 2011-09-02 08:45:20.000000000 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6476261
+ * @summary More testing of parsing of signatures attributes of nested classes
+ */
+
+import java.lang.reflect.*;
+
+public class SignatureTest {
+ class Inner1 {
+ class Inner11 {
+ }
+ }
+
+ public void f(SignatureTest.Inner1.Inner11 x) {}
+ public void g(SignatureTest.Inner1 x) {}
+
+ public static void main(String[] args) throws Exception {
+ Class clazz = SignatureTest.class;
+ for (Method m : clazz.getDeclaredMethods()) {
+ System.out.println();
+ System.out.println(m.toString());
+ System.out.println(m.toGenericString());
+ System.out.println(m.getGenericParameterTypes());
+ }
+ }
+}
--- /dev/null 2011-09-01 02:03:34.128260089 -0700
+++ new/test/java/lang/reflect/Generics/TestBadSignatures.java 2011-09-02 08:45:20.000000000 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6832374 7052898
+ * @summary Test bad signatures get a GenericSignatureFormatError thrown.
+ * @author Joseph D. Darcy
+ */
+
+import java.lang.reflect.*;
+import sun.reflect.generics.parser.SignatureParser;
+
+public class TestBadSignatures {
+ public static void main(String[] args) {
+ String[] badSignatures = {
+ // Missing ":" after first type bound
+ "(TE;[Ljava/lang/RuntimeException;)V^[TE;",
+ };
+
+ for(String badSig : badSignatures) {
+ try {
+ SignatureParser.make().parseMethodSig(badSig);
+ throw new RuntimeException("Expected GenericSignatureFormatError for " +
+ badSig);
+ } catch(GenericSignatureFormatError gsfe) {
+ System.out.println(gsfe.toString()); // Expected
+ }
+ }
+ }
+}