6476261: (reflect) GenericSignatureFormatError When signature includes nested inner classes
6832374: (reflect) malformed signature can cause parser to go into infinite loop 7052898: (reflect) SignatureParser will accept strings outside of the grammar Various signature parsing fixes; additional review by sonali.goel@oracle.com Reviewed-by: alanb
This commit is contained in:
parent
765c6904e3
commit
d0bd4f51ce
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,17 +25,15 @@
|
|||||||
|
|
||||||
package sun.reflect.generics.parser;
|
package sun.reflect.generics.parser;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.GenericSignatureFormatError;
|
import java.lang.reflect.GenericSignatureFormatError;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import sun.reflect.generics.tree.*;
|
import sun.reflect.generics.tree.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parser for type signatures, as defined in the Java Virtual
|
* 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.
|
* 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 {
|
public class SignatureParser {
|
||||||
// The input is conceptually a character stream (though currently it's
|
// The input is conceptually a character stream (though currently it's
|
||||||
@ -58,8 +56,8 @@ public class SignatureParser {
|
|||||||
// if (current != x {error("expected an x");
|
// if (current != x {error("expected an x");
|
||||||
//
|
//
|
||||||
// where x is some character constant.
|
// where x is some character constant.
|
||||||
// The assertion inidcates, that, as currently written,
|
// The assertion indicates, that, as currently written,
|
||||||
// the code should nver reach this point unless the input is an
|
// 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
|
// 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
|
// 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
|
// time the code might be called directly, and if the input is
|
||||||
@ -68,7 +66,7 @@ public class SignatureParser {
|
|||||||
|
|
||||||
private char[] input; // the input signature
|
private char[] input; // the input signature
|
||||||
private int index = 0; // index into the input
|
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 char EOI = ':';
|
||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
@ -104,6 +102,11 @@ public class SignatureParser {
|
|||||||
index++;
|
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
|
// Match c against a "set" of characters
|
||||||
private boolean matches(char c, char... set) {
|
private boolean matches(char c, char... set) {
|
||||||
for (char e : set) {
|
for (char e : set) {
|
||||||
@ -117,8 +120,17 @@ public class SignatureParser {
|
|||||||
// Currently throws a GenericSignatureFormatError.
|
// Currently throws a GenericSignatureFormatError.
|
||||||
|
|
||||||
private Error error(String errorMsg) {
|
private Error error(String errorMsg) {
|
||||||
if (DEBUG) System.out.println("Parse error:" + errorMsg);
|
return new GenericSignatureFormatError("Signature Parse error: " + errorMsg +
|
||||||
return new GenericSignatureFormatError();
|
"\n\tRemaining input: " + remainder());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,6 +175,7 @@ public class SignatureParser {
|
|||||||
/**
|
/**
|
||||||
* Parses a type signature
|
* Parses a type signature
|
||||||
* and produces an abstract syntax tree representing it.
|
* and produces an abstract syntax tree representing it.
|
||||||
|
*
|
||||||
* @param s a string representing the input type signature
|
* @param s a string representing the input type signature
|
||||||
* @return An abstract syntax tree for a type signature
|
* @return An abstract syntax tree for a type signature
|
||||||
* corresponding to the input string
|
* corresponding to the input string
|
||||||
@ -183,38 +196,58 @@ public class SignatureParser {
|
|||||||
// and when it completes parsing, it leaves the input at the first
|
// and when it completes parsing, it leaves the input at the first
|
||||||
// character after the input parses.
|
// 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() {
|
private ClassSignature parseClassSignature() {
|
||||||
|
// parse a class signature based on the implicit input.
|
||||||
assert(index == 0);
|
assert(index == 0);
|
||||||
return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
|
return ClassSignature.make(parseZeroOrMoreFormalTypeParameters(),
|
||||||
parseClassTypeSignature(),
|
parseClassTypeSignature(), // Only rule for SuperclassSignature
|
||||||
parseSuperInterfaces());
|
parseSuperInterfaces());
|
||||||
}
|
}
|
||||||
|
|
||||||
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
|
private FormalTypeParameter[] parseZeroOrMoreFormalTypeParameters(){
|
||||||
if (current() == '<') { return parseFormalTypeParameters();}
|
if (current() == '<') {
|
||||||
else {return new FormalTypeParameter[0];}
|
return parseFormalTypeParameters();
|
||||||
|
} else {
|
||||||
|
return new FormalTypeParameter[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FormalTypeParameters:
|
||||||
|
* "<" FormalTypeParameter+ ">"
|
||||||
|
*/
|
||||||
private FormalTypeParameter[] parseFormalTypeParameters(){
|
private FormalTypeParameter[] parseFormalTypeParameters(){
|
||||||
Collection<FormalTypeParameter> ftps =
|
List<FormalTypeParameter> ftps = new ArrayList<>(3);
|
||||||
new ArrayList<FormalTypeParameter>(3);
|
|
||||||
assert(current() == '<'); // should not have been called at all
|
assert(current() == '<'); // should not have been called at all
|
||||||
if (current() != '<') { throw error("expected <");}
|
if (current() != '<') { throw error("expected '<'");}
|
||||||
advance();
|
advance();
|
||||||
ftps.add(parseFormalTypeParameter());
|
ftps.add(parseFormalTypeParameter());
|
||||||
while (current() != '>') {
|
while (current() != '>') {
|
||||||
|
int startingPosition = index;
|
||||||
ftps.add(parseFormalTypeParameter());
|
ftps.add(parseFormalTypeParameter());
|
||||||
|
progress(startingPosition);
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
FormalTypeParameter[] ftpa = new FormalTypeParameter[ftps.size()];
|
return ftps.toArray(new FormalTypeParameter[ftps.size()]);
|
||||||
return ftps.toArray(ftpa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FormalTypeParameter:
|
||||||
|
* Identifier ClassBound InterfaceBound*
|
||||||
|
*/
|
||||||
private FormalTypeParameter parseFormalTypeParameter(){
|
private FormalTypeParameter parseFormalTypeParameter(){
|
||||||
String id = parseIdentifier();
|
String id = parseIdentifier();
|
||||||
FieldTypeSignature[] bs = parseZeroOrMoreBounds();
|
FieldTypeSignature[] bs = parseBounds();
|
||||||
return FormalTypeParameter.make(id, bs);
|
return FormalTypeParameter.make(id, bs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +262,8 @@ public class SignatureParser {
|
|||||||
case '[':
|
case '[':
|
||||||
case ':':
|
case ':':
|
||||||
case '>':
|
case '>':
|
||||||
case '<': return result.toString();
|
case '<':
|
||||||
|
return result.toString();
|
||||||
default:{
|
default:{
|
||||||
result.append(c);
|
result.append(c);
|
||||||
advance();
|
advance();
|
||||||
@ -239,26 +273,42 @@ public class SignatureParser {
|
|||||||
}
|
}
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* FieldTypeSignature:
|
||||||
|
* ClassTypeSignature
|
||||||
|
* ArrayTypeSignature
|
||||||
|
* TypeVariableSignature
|
||||||
|
*/
|
||||||
private FieldTypeSignature parseFieldTypeSignature() {
|
private FieldTypeSignature parseFieldTypeSignature() {
|
||||||
|
return parseFieldTypeSignature(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldTypeSignature parseFieldTypeSignature(boolean allowArrays) {
|
||||||
switch(current()) {
|
switch(current()) {
|
||||||
case 'L':
|
case 'L':
|
||||||
return parseClassTypeSignature();
|
return parseClassTypeSignature();
|
||||||
case 'T':
|
case 'T':
|
||||||
return parseTypeVariableSignature();
|
return parseTypeVariableSignature();
|
||||||
case '[':
|
case '[':
|
||||||
|
if (allowArrays)
|
||||||
return parseArrayTypeSignature();
|
return parseArrayTypeSignature();
|
||||||
|
else
|
||||||
|
throw error("Array signature not allowed here.");
|
||||||
default: throw error("Expected Field Type Signature");
|
default: throw error("Expected Field Type Signature");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassTypeSignature:
|
||||||
|
* "L" PackageSpecifier_opt SimpleClassTypeSignature ClassTypeSignatureSuffix* ";"
|
||||||
|
*/
|
||||||
private ClassTypeSignature parseClassTypeSignature(){
|
private ClassTypeSignature parseClassTypeSignature(){
|
||||||
assert(current() == 'L');
|
assert(current() == 'L');
|
||||||
if (current() != 'L') { throw error("expected a class type");}
|
if (current() != 'L') { throw error("expected a class type");}
|
||||||
advance();
|
advance();
|
||||||
List<SimpleClassTypeSignature> scts =
|
List<SimpleClassTypeSignature> scts = new ArrayList<>(5);
|
||||||
new ArrayList<SimpleClassTypeSignature>(5);
|
scts.add(parsePackageNameAndSimpleClassTypeSignature());
|
||||||
scts.add(parseSimpleClassTypeSignature(false));
|
|
||||||
parseClassTypeSignatureSuffix(scts);
|
parseClassTypeSignatureSuffix(scts);
|
||||||
if (current() != ';')
|
if (current() != ';')
|
||||||
throw error("expected ';' got '" + current() + "'");
|
throw error("expected ';' got '" + current() + "'");
|
||||||
@ -267,25 +317,65 @@ public class SignatureParser {
|
|||||||
return ClassTypeSignature.make(scts);
|
return ClassTypeSignature.make(scts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleClassTypeSignature parseSimpleClassTypeSignature(boolean dollar){
|
/**
|
||||||
|
* PackageSpecifier:
|
||||||
|
* Identifier "/" PackageSpecifier*
|
||||||
|
*/
|
||||||
|
private SimpleClassTypeSignature parsePackageNameAndSimpleClassTypeSignature() {
|
||||||
|
// Parse both any optional leading PackageSpecifier as well as
|
||||||
|
// the following SimpleClassTypeSignature.
|
||||||
|
|
||||||
String id = parseIdentifier();
|
String id = parseIdentifier();
|
||||||
char c = current();
|
|
||||||
switch (c) {
|
if (current() == '/') { // package name
|
||||||
case ';':
|
StringBuilder idBuild = new StringBuilder(id);
|
||||||
case '/':
|
|
||||||
return SimpleClassTypeSignature.make(id, dollar, new TypeArgument[0]) ;
|
while(current() == '/') {
|
||||||
case '<': {
|
advance();
|
||||||
return SimpleClassTypeSignature.make(id, dollar, parseTypeArguments());
|
idBuild.append(".");
|
||||||
|
idBuild.append(parseIdentifier());
|
||||||
}
|
}
|
||||||
default: {throw error("expected < or ; or /");}
|
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<SimpleClassTypeSignature> scts) {
|
private void parseClassTypeSignatureSuffix(List<SimpleClassTypeSignature> scts) {
|
||||||
while (current() == '/' || current() == '.') {
|
while (current() == '.') {
|
||||||
boolean dollar = (current() == '.');
|
|
||||||
advance();
|
advance();
|
||||||
scts.add(parseSimpleClassTypeSignature(dollar));
|
scts.add(parseSimpleClassTypeSignature(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,10 +384,14 @@ public class SignatureParser {
|
|||||||
else {return new TypeArgument[0];}
|
else {return new TypeArgument[0];}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TypeArguments:
|
||||||
|
* "<" TypeArgument+ ">"
|
||||||
|
*/
|
||||||
private TypeArgument[] parseTypeArguments() {
|
private TypeArgument[] parseTypeArguments() {
|
||||||
Collection<TypeArgument> tas = new ArrayList<TypeArgument>(3);
|
List<TypeArgument> tas = new ArrayList<>(3);
|
||||||
assert(current() == '<');
|
assert(current() == '<');
|
||||||
if (current() != '<') { throw error("expected <");}
|
if (current() != '<') { throw error("expected '<'");}
|
||||||
advance();
|
advance();
|
||||||
tas.add(parseTypeArgument());
|
tas.add(parseTypeArgument());
|
||||||
while (current() != '>') {
|
while (current() != '>') {
|
||||||
@ -305,10 +399,14 @@ public class SignatureParser {
|
|||||||
tas.add(parseTypeArgument());
|
tas.add(parseTypeArgument());
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
TypeArgument[] taa = new TypeArgument[tas.size()];
|
return tas.toArray(new TypeArgument[tas.size()]);
|
||||||
return tas.toArray(taa);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TypeArgument:
|
||||||
|
* WildcardIndicator_opt FieldTypeSignature
|
||||||
|
* "*"
|
||||||
|
*/
|
||||||
private TypeArgument parseTypeArgument() {
|
private TypeArgument parseTypeArgument() {
|
||||||
FieldTypeSignature[] ub, lb;
|
FieldTypeSignature[] ub, lb;
|
||||||
ub = new FieldTypeSignature[1];
|
ub = new FieldTypeSignature[1];
|
||||||
@ -334,18 +432,20 @@ public class SignatureParser {
|
|||||||
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
|
ub[0] = SimpleClassTypeSignature.make("java.lang.Object", false, ta);
|
||||||
return Wildcard.make(ub, lb);
|
return Wildcard.make(ub, lb);
|
||||||
}
|
}
|
||||||
default: return parseFieldTypeSignature();
|
default:
|
||||||
|
return parseFieldTypeSignature();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeVariableSignature -> T identifier
|
/**
|
||||||
|
* TypeVariableSignature:
|
||||||
private TypeVariableSignature parseTypeVariableSignature(){
|
* "T" Identifier ";"
|
||||||
|
*/
|
||||||
|
private TypeVariableSignature parseTypeVariableSignature() {
|
||||||
assert(current() == 'T');
|
assert(current() == 'T');
|
||||||
if (current() != 'T') { throw error("expected a type variable usage");}
|
if (current() != 'T') { throw error("expected a type variable usage");}
|
||||||
advance();
|
advance();
|
||||||
TypeVariableSignature ts =
|
TypeVariableSignature ts = TypeVariableSignature.make(parseIdentifier());
|
||||||
TypeVariableSignature.make(parseIdentifier());
|
|
||||||
if (current() != ';') {
|
if (current() != ';') {
|
||||||
throw error("; expected in signature of type variable named" +
|
throw error("; expected in signature of type variable named" +
|
||||||
ts.getIdentifier());
|
ts.getIdentifier());
|
||||||
@ -354,16 +454,21 @@ public class SignatureParser {
|
|||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayTypeSignature -> [ TypeSignature
|
/**
|
||||||
|
* ArrayTypeSignature:
|
||||||
|
* "[" TypeSignature
|
||||||
|
*/
|
||||||
private ArrayTypeSignature parseArrayTypeSignature() {
|
private ArrayTypeSignature parseArrayTypeSignature() {
|
||||||
if (current() != '[') {throw error("expected array type signature");}
|
if (current() != '[') {throw error("expected array type signature");}
|
||||||
advance();
|
advance();
|
||||||
return ArrayTypeSignature.make(parseTypeSignature());
|
return ArrayTypeSignature.make(parseTypeSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeSignature -> BaseType | FieldTypeSignature
|
/**
|
||||||
|
* TypeSignature:
|
||||||
|
* FieldTypeSignature
|
||||||
|
* BaseType
|
||||||
|
*/
|
||||||
private TypeSignature parseTypeSignature() {
|
private TypeSignature parseTypeSignature() {
|
||||||
switch (current()) {
|
switch (current()) {
|
||||||
case 'B':
|
case 'B':
|
||||||
@ -373,8 +478,11 @@ public class SignatureParser {
|
|||||||
case 'I':
|
case 'I':
|
||||||
case 'J':
|
case 'J':
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'Z':return parseBaseType();
|
case 'Z':
|
||||||
default: return parseFieldTypeSignature();
|
return parseBaseType();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return parseFieldTypeSignature();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,9 +519,15 @@ public class SignatureParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FieldTypeSignature[] parseZeroOrMoreBounds() {
|
/**
|
||||||
Collection<FieldTypeSignature> fts =
|
* ClassBound:
|
||||||
new ArrayList<FieldTypeSignature>(3);
|
* ":" FieldTypeSignature_opt
|
||||||
|
*
|
||||||
|
* InterfaceBound:
|
||||||
|
* ":" FieldTypeSignature
|
||||||
|
*/
|
||||||
|
private FieldTypeSignature[] parseBounds() {
|
||||||
|
List<FieldTypeSignature> fts = new ArrayList<>(3);
|
||||||
|
|
||||||
if (current() == ':') {
|
if (current() == ':') {
|
||||||
advance();
|
advance();
|
||||||
@ -430,24 +544,31 @@ public class SignatureParser {
|
|||||||
advance();
|
advance();
|
||||||
fts.add(parseFieldTypeSignature());
|
fts.add(parseFieldTypeSignature());
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
error("Bound expected");
|
||||||
|
|
||||||
|
return fts.toArray(new FieldTypeSignature[fts.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldTypeSignature[] fta = new FieldTypeSignature[fts.size()];
|
/**
|
||||||
return fts.toArray(fta);
|
* SuperclassSignature:
|
||||||
}
|
* ClassTypeSignature
|
||||||
|
*/
|
||||||
private ClassTypeSignature[] parseSuperInterfaces() {
|
private ClassTypeSignature[] parseSuperInterfaces() {
|
||||||
Collection<ClassTypeSignature> cts =
|
List<ClassTypeSignature> cts = new ArrayList<>(5);
|
||||||
new ArrayList<ClassTypeSignature>(5);
|
|
||||||
while(current() == 'L') {
|
while(current() == 'L') {
|
||||||
cts.add(parseClassTypeSignature());
|
cts.add(parseClassTypeSignature());
|
||||||
}
|
}
|
||||||
ClassTypeSignature[] cta = new ClassTypeSignature[cts.size()];
|
return cts.toArray(new ClassTypeSignature[cts.size()]);
|
||||||
return cts.toArray(cta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse a method signature based on the implicit input.
|
|
||||||
|
/**
|
||||||
|
* MethodTypeSignature:
|
||||||
|
* FormalTypeParameters_opt "(" TypeSignature* ")" ReturnType ThrowsSignature*
|
||||||
|
*/
|
||||||
private MethodTypeSignature parseMethodTypeSignature() {
|
private MethodTypeSignature parseMethodTypeSignature() {
|
||||||
|
// Parse a method signature based on the implicit input.
|
||||||
FieldTypeSignature[] ets;
|
FieldTypeSignature[] ets;
|
||||||
|
|
||||||
assert(index == 0);
|
assert(index == 0);
|
||||||
@ -457,19 +578,19 @@ public class SignatureParser {
|
|||||||
parseZeroOrMoreThrowsSignatures());
|
parseZeroOrMoreThrowsSignatures());
|
||||||
}
|
}
|
||||||
|
|
||||||
// (TypeSignature*)
|
// "(" TypeSignature* ")"
|
||||||
private TypeSignature[] parseFormalParameters() {
|
private TypeSignature[] parseFormalParameters() {
|
||||||
if (current() != '(') {throw error("expected (");}
|
if (current() != '(') {throw error("expected '('");}
|
||||||
advance();
|
advance();
|
||||||
TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
|
TypeSignature[] pts = parseZeroOrMoreTypeSignatures();
|
||||||
if (current() != ')') {throw error("expected )");}
|
if (current() != ')') {throw error("expected ')'");}
|
||||||
advance();
|
advance();
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeSignature*
|
// TypeSignature*
|
||||||
private TypeSignature[] parseZeroOrMoreTypeSignatures() {
|
private TypeSignature[] parseZeroOrMoreTypeSignatures() {
|
||||||
Collection<TypeSignature> ts = new ArrayList<TypeSignature>();
|
List<TypeSignature> ts = new ArrayList<>();
|
||||||
boolean stop = false;
|
boolean stop = false;
|
||||||
while (!stop) {
|
while (!stop) {
|
||||||
switch(current()) {
|
switch(current()) {
|
||||||
@ -490,41 +611,40 @@ public class SignatureParser {
|
|||||||
default: stop = true;
|
default: stop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* while( matches(current(),
|
return ts.toArray(new TypeSignature[ts.size()]);
|
||||||
'B', 'C', 'D', 'F', 'I', 'J', 'S', 'Z', 'L', 'T', '[')
|
|
||||||
) {
|
|
||||||
ts.add(parseTypeSignature());
|
|
||||||
}*/
|
|
||||||
TypeSignature[] ta = new TypeSignature[ts.size()];
|
|
||||||
return ts.toArray(ta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReturnType -> V | TypeSignature
|
/**
|
||||||
|
* ReturnType:
|
||||||
|
* TypeSignature
|
||||||
|
* VoidDescriptor
|
||||||
|
*/
|
||||||
private ReturnType parseReturnType(){
|
private ReturnType parseReturnType(){
|
||||||
if (current() == 'V') {
|
if (current() == 'V') {
|
||||||
advance();
|
advance();
|
||||||
return VoidDescriptor.make();
|
return VoidDescriptor.make();
|
||||||
} else return parseTypeSignature();
|
} else
|
||||||
|
return parseTypeSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThrowSignature*
|
// ThrowSignature*
|
||||||
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
|
private FieldTypeSignature[] parseZeroOrMoreThrowsSignatures(){
|
||||||
Collection<FieldTypeSignature> ets =
|
List<FieldTypeSignature> ets = new ArrayList<>(3);
|
||||||
new ArrayList<FieldTypeSignature>(3);
|
|
||||||
while( current() == '^') {
|
while( current() == '^') {
|
||||||
ets.add(parseThrowsSignature());
|
ets.add(parseThrowsSignature());
|
||||||
}
|
}
|
||||||
FieldTypeSignature[] eta = new FieldTypeSignature[ets.size()];
|
return ets.toArray(new FieldTypeSignature[ets.size()]);
|
||||||
return ets.toArray(eta);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThrowSignature -> ^ FieldTypeSignature
|
/**
|
||||||
|
* ThrowsSignature:
|
||||||
|
* "^" ClassTypeSignature
|
||||||
|
* "^" TypeVariableSignature
|
||||||
|
*/
|
||||||
private FieldTypeSignature parseThrowsSignature() {
|
private FieldTypeSignature parseThrowsSignature() {
|
||||||
assert(current() == '^');
|
assert(current() == '^');
|
||||||
if (current() != '^') { throw error("expected throws signature");}
|
if (current() != '^') { throw error("expected throws signature");}
|
||||||
advance();
|
advance();
|
||||||
return parseFieldTypeSignature();
|
return parseFieldTypeSignature(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 5003916 6704655 6873951
|
* @bug 5003916 6704655 6873951 6476261
|
||||||
* @summary Testing parsing of signatures attributes of nested classes
|
* @summary Testing parsing of signatures attributes of nested classes
|
||||||
* @author Joseph D. Darcy
|
* @author Joseph D. Darcy
|
||||||
*/
|
*/
|
||||||
@ -38,12 +38,12 @@ import static java.util.Arrays.*;
|
|||||||
"java.util.concurrent.ConcurrentHashMap$KeyIterator",
|
"java.util.concurrent.ConcurrentHashMap$KeyIterator",
|
||||||
"java.util.concurrent.ConcurrentHashMap$ValueIterator",
|
"java.util.concurrent.ConcurrentHashMap$ValueIterator",
|
||||||
"java.util.AbstractList$ListItr",
|
"java.util.AbstractList$ListItr",
|
||||||
// "java.util.EnumMap$EntryIterator",
|
"java.util.EnumMap$EntryIterator",
|
||||||
// "java.util.EnumMap$KeyIterator",
|
"java.util.EnumMap$KeyIterator",
|
||||||
// "java.util.EnumMap$ValueIterator",
|
"java.util.EnumMap$ValueIterator",
|
||||||
// "java.util.IdentityHashMap$EntryIterator",
|
"java.util.IdentityHashMap$EntryIterator",
|
||||||
// "java.util.IdentityHashMap$KeyIterator",
|
"java.util.IdentityHashMap$KeyIterator",
|
||||||
// "java.util.IdentityHashMap$ValueIterator",
|
"java.util.IdentityHashMap$ValueIterator",
|
||||||
"java.util.WeakHashMap$EntryIterator",
|
"java.util.WeakHashMap$EntryIterator",
|
||||||
"java.util.WeakHashMap$KeyIterator",
|
"java.util.WeakHashMap$KeyIterator",
|
||||||
"java.util.WeakHashMap$ValueIterator",
|
"java.util.WeakHashMap$ValueIterator",
|
||||||
@ -52,12 +52,12 @@ import static java.util.Arrays.*;
|
|||||||
"java.util.HashMap$ValueIterator",
|
"java.util.HashMap$ValueIterator",
|
||||||
"java.util.LinkedHashMap$EntryIterator",
|
"java.util.LinkedHashMap$EntryIterator",
|
||||||
"java.util.LinkedHashMap$KeyIterator",
|
"java.util.LinkedHashMap$KeyIterator",
|
||||||
"java.util.LinkedHashMap$ValueIterator"})
|
"java.util.LinkedHashMap$ValueIterator",
|
||||||
|
"javax.swing.JComboBox$AccessibleJComboBox"})
|
||||||
public class Probe {
|
public class Probe {
|
||||||
public static void main (String... args) throws Throwable {
|
public static void main (String... args) throws Throwable {
|
||||||
Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class);
|
Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class);
|
||||||
List<String> names =
|
List<String> names = new ArrayList<>(asList(classesAnnotation.value()));
|
||||||
new ArrayList<String>(asList(classesAnnotation.value()));
|
|
||||||
|
|
||||||
int errs = 0;
|
int errs = 0;
|
||||||
for(String name: names) {
|
for(String name: names) {
|
||||||
|
50
jdk/test/java/lang/reflect/Generics/SignatureTest.java
Normal file
50
jdk/test/java/lang/reflect/Generics/SignatureTest.java
Normal file
@ -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<T> {
|
||||||
|
class Inner1 {
|
||||||
|
class Inner11 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void f(SignatureTest<String>.Inner1.Inner11 x) {}
|
||||||
|
public void g(SignatureTest<String>.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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
jdk/test/java/lang/reflect/Generics/TestBadSignatures.java
Normal file
54
jdk/test/java/lang/reflect/Generics/TestBadSignatures.java
Normal file
@ -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
|
||||||
|
"<T:Lfoo/tools/nsc/symtab/Names;Lfoo/tools/nsc/symtab/Symbols;",
|
||||||
|
|
||||||
|
// Arrays improperly indicated for exception information
|
||||||
|
"<E:Ljava/lang/Exception;>(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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user