Browse Source

406167: cope with rogue generic inner type signatures

tags/V1_8_6
Andy Clement 9 years ago
parent
commit
c6753a8aaf

+ 36
- 20
util/src/org/aspectj/util/GenericSignatureParser.java View File

@@ -187,18 +187,10 @@ public class GenericSignatureParser {
// now we have either a "." indicating the start of a nested type,
// or a "<" indication type arguments, or ";" and we are done.
while (!maybeEat(";")) {
if (maybeEat(".")) {
if (tokenStream[tokenIndex].equals(".")) {
// outer type completed
outerType = new SimpleClassTypeSignature(identifier);
List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
do {
ret.append(".");
SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
ret.append(sig.toString());
nestedTypeList.add(sig);
} while (maybeEat("."));
nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
nestedTypeList.toArray(nestedTypes);
nestedTypes = parseNestedTypesHelper(ret);
} else if (tokenStream[tokenIndex].equals("<")) {
ret.append("<");
TypeArgument[] tArgs = maybeParseTypeArguments();
@@ -207,16 +199,7 @@ public class GenericSignatureParser {
}
ret.append(">");
outerType = new SimpleClassTypeSignature(identifier, tArgs);
// now parse possible nesteds...
List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
while (maybeEat(".")) {
ret.append(".");
SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
ret.append(sig.toString());
nestedTypeList.add(sig);
}
nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
nestedTypeList.toArray(nestedTypes);
nestedTypes = parseNestedTypesHelper(ret);
} else {
throw new IllegalStateException("Expecting .,<, or ;, but found " + tokenStream[tokenIndex] + " while unpacking "
+ inputString);
@@ -228,6 +211,39 @@ public class GenericSignatureParser {
return new ClassTypeSignature(ret.toString(), outerType, nestedTypes);
}

/**
* Helper method to digest nested types, slightly more complex than necessary to cope with some android related
* incorrect classes (see bug 406167)
*/
private SimpleClassTypeSignature[] parseNestedTypesHelper(StringBuffer ret) {
boolean brokenSignature = false;
SimpleClassTypeSignature[] nestedTypes;
List<SimpleClassTypeSignature> nestedTypeList = new ArrayList<SimpleClassTypeSignature>();
while (maybeEat(".")) {
ret.append(".");
SimpleClassTypeSignature sig = parseSimpleClassTypeSignature();
if (tokenStream[tokenIndex].equals("/")) {
if (!brokenSignature) {
System.err.println("[See bug 406167] Bad class file signature encountered, nested types appear package qualified, ignoring those incorrect pieces. Signature: "+inputString);
}
brokenSignature = true;
// hit something like: Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;
// and we are looking at the '/' after the com
tokenIndex++; // pointing at the next identifier
while (tokenStream[tokenIndex+1].equals("/")) {
tokenIndex+=2; // jump over an 'identifier' '/' pair
}
// now tokenIndex is the final bit of the name (which we'll treat as the inner type name)
sig = parseSimpleClassTypeSignature();
}
ret.append(sig.toString());
nestedTypeList.add(sig);
};
nestedTypes = new SimpleClassTypeSignature[nestedTypeList.size()];
nestedTypeList.toArray(nestedTypes);
return nestedTypes;
}

private SimpleClassTypeSignature parseSimpleClassTypeSignature() {
String identifier = eatIdentifier();
TypeArgument[] tArgs = maybeParseTypeArguments();

+ 22
- 1
util/testsrc/org/aspectj/util/GenericSignatureParserTest.java View File

@@ -95,6 +95,27 @@ public class GenericSignatureParserTest extends TestCase {
assertEquals("Ljava/util/Comparable<-TE;>;", sig.superInterfaceSignatures[0].toString());
}

public void testFunky_406167() {
ClassSignature sig = parser
.parseAsClassSignature("Lcom/google/android/gms/internal/hb<TT;>.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
// Note the package prefix on the nested types has been dropped
assertEquals("Lcom/google/android/gms/internal/hb<TT;>.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
sig = parser
.parseAsClassSignature("Lcom/a/a/b/t<TK;TV;>.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
// Note the package prefix on the nested types has been dropped
assertEquals("Lcom/a/a/b/t<TK;TV;>.af.ag;",sig.superclassSignature.toString());
assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
sig = parser.parseAsClassSignature("Lcom/google/android/gms/internal/hb.com/google/android/gms/internal/hb$b<Ljava/lang/Boolean;>;");
// Note the package prefix on the nested types has been dropped
assertEquals("Lcom/google/android/gms/internal/hb.hb$b<Ljava/lang/Boolean;>;",sig.superclassSignature.toString());
sig = parser
.parseAsClassSignature("Lcom/a/a/b/t.com/a/a/b/af.com/a/a/b/ag;Ljava/util/ListIterator<TV;>;");
// Note the package prefix on the nested types has been dropped
assertEquals("Lcom/a/a/b/t.af.ag;",sig.superclassSignature.toString());
assertEquals("Ljava/util/ListIterator<TV;>;",sig.superInterfaceSignatures[0].toString());
}


public void testFieldSignatureParsingClassType() {
FieldTypeSignature fsig = parser.parseAsFieldSignature("Ljava/lang/String;");
assertTrue("ClassTypeSignature", fsig instanceof ClassTypeSignature);
@@ -155,7 +176,7 @@ public class GenericSignatureParserTest extends TestCase {
assertEquals("Ljava/lang/Exception;", mSig.throwsSignatures[0].toString());
assertEquals("Ljava/lang/RuntimeException;", mSig.throwsSignatures[1].toString());
}
public void testMethodSignaturePrimitiveParams() {
GenericSignature.MethodTypeSignature mSig = parser.parseAsMethodSignature("(ILjava/lang/Object;)V");
assertEquals("2 parameters", 2, mSig.parameters.length);

Loading…
Cancel
Save