diff options
author | acolyer <acolyer> | 2005-07-28 10:56:10 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-07-28 10:56:10 +0000 |
commit | 2fd6898f0a4fcc4bd0a3d142b10cff44b131b022 (patch) | |
tree | fe1099f6bf9622bfa96a137752fa28f929baac8c /weaver | |
parent | b94dee2854b998ccd1bc1738e91f0ce36e781cbb (diff) | |
download | aspectj-2fd6898f0a4fcc4bd0a3d142b10cff44b131b022.tar.gz aspectj-2fd6898f0a4fcc4bd0a3d142b10cff44b131b022.zip |
parser updates for generics simplification plan
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/org/aspectj/weaver/patterns/PatternParser.java | 108 | ||||
-rw-r--r-- | weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java | 187 |
2 files changed, 161 insertions, 134 deletions
diff --git a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java index ae4e77cdd..b108b57b1 100644 --- a/weaver/src/org/aspectj/weaver/patterns/PatternParser.java +++ b/weaver/src/org/aspectj/weaver/patterns/PatternParser.java @@ -1,5 +1,6 @@ /* ******************************************************************* * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * 2005 Contributors * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Common Public License v1.0 @@ -7,7 +8,8 @@ * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: - * PARC initial implementation + * PARC initial implementation + * Adrian Colyer many updates since.... * ******************************************************************/ @@ -182,9 +184,12 @@ public class PatternParser { } private Declare parseParents() { - String[] typeParameters = maybeParseSimpleTypeVariableList(); + /* + * simplified design requires use of raw types for declare parents, no generic spec. allowed + * String[] typeParameters = maybeParseSimpleTypeVariableList(); + */ eat(":"); - TypePattern p = parseTypePattern(false,false); + TypePattern p = parseTypePattern(false); IToken t = tokenSource.next(); if (!(t.getString().equals("extends") || t.getString().equals("implements"))) { throw new ParserException("extends or implements", t); @@ -198,9 +203,6 @@ public class PatternParser { //XXX somewhere in the chain we need to enforce that we have only ExactTypePatterns DeclareParents decp = new DeclareParents(p, l); - if (typeParameters != null) { - decp.setTypeParametersInScope(typeParameters); - } return decp; } @@ -278,44 +280,26 @@ public class PatternParser { } String kind = parseIdentifier(); - IToken possibleTypeVariableToken = tokenSource.peek(); - String[] typeVariables = maybeParseSimpleTypeVariableList(); +// IToken possibleTypeVariableToken = tokenSource.peek(); +// String[] typeVariables = maybeParseSimpleTypeVariableList(); if (kind.equals("execution") || kind.equals("call") || kind.equals("get") || kind.equals("set")) { p = parseKindedPointcut(kind); } else if (kind.equals("args")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); p = parseArgsPointcut(); } else if (kind.equals("this")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); p = parseThisOrTargetPointcut(kind); } else if (kind.equals("target")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); p = parseThisOrTargetPointcut(kind); } else if (kind.equals("within")) { p = parseWithinPointcut(); } else if (kind.equals("withincode")) { p = parseWithinCodePointcut(); } else if (kind.equals("cflow")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); p = parseCflowPointcut(false); } else if (kind.equals("cflowbelow")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); p = parseCflowPointcut(true); } else if (kind.equals("adviceexecution")) { - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); eat("("); eat(")"); p = new KindedPointcut(Shadow.AdviceExecution, @@ -325,9 +309,8 @@ public class PatternParser { ThrowsPattern.ANY, AnnotationTypePattern.ANY)); } else if (kind.equals("handler")) { - assertNoTypeVariables(typeVariables,"(",possibleTypeVariableToken); eat("("); - TypePattern typePat = parseTypePattern(false,true); + TypePattern typePat = parseTypePattern(false); eat(")"); p = new HandlerPointcut(typePat); } else if (kind.equals("initialization")) { @@ -337,7 +320,7 @@ public class PatternParser { p = new KindedPointcut(Shadow.Initialization, sig); } else if (kind.equals("staticinitialization")) { eat("("); - TypePattern typePat = parseTypePattern(false,true); + TypePattern typePat = parseTypePattern(false); eat(")"); p = new KindedPointcut(Shadow.StaticInitialization, new SignaturePattern(Member.STATIC_INITIALIZATION, ModifiersPattern.ANY, @@ -350,9 +333,6 @@ public class PatternParser { p = new KindedPointcut(Shadow.PreInitialization, sig); } else if (kind.equals("if")) { // @style support allows if(), if(true), if(false) - assertNoTypeVariables(typeVariables, - "(" - , possibleTypeVariableToken); eat("("); if (maybeEatIdentifier("true")) { eat(")"); @@ -369,10 +349,7 @@ public class PatternParser { else { tokenSource.setIndex(start); p = parseReferencePointcut(); - if (typeVariables != null) - throw new ParserException("type variable specification not allowed for reference pointcuts",possibleTypeVariableToken); } - if (typeVariables != null) p.setTypeVariablesInScope(typeVariables); return p; } @@ -573,40 +550,40 @@ public class PatternParser { } public TypePattern parseTypePattern() { - return parseTypePattern(false,false); + return parseTypePattern(false); } - public TypePattern parseTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) { - TypePattern p = parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations); + public TypePattern parseTypePattern(boolean insideTypeParameters) { + TypePattern p = parseAtomicTypePattern(insideTypeParameters); if (maybeEat("&&")) { - p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters,allowTypeVariableDeclarations)); + p = new AndTypePattern(p, parseNotOrTypePattern(insideTypeParameters)); } if (maybeEat("||")) { - p = new OrTypePattern(p, parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations)); + p = new OrTypePattern(p, parseTypePattern(insideTypeParameters)); } return p; } - private TypePattern parseNotOrTypePattern(boolean insideTypeParameters,boolean allowTypeVariableDeclarations) { - TypePattern p = parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations); + private TypePattern parseNotOrTypePattern(boolean insideTypeParameters) { + TypePattern p = parseAtomicTypePattern(insideTypeParameters); if (maybeEat("&&")) { - p = new AndTypePattern(p, parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations)); + p = new AndTypePattern(p, parseTypePattern(insideTypeParameters)); } return p; } - private TypePattern parseAtomicTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) { + private TypePattern parseAtomicTypePattern(boolean insideTypeParameters) { AnnotationTypePattern ap = maybeParseAnnotationPattern(); if (maybeEat("!")) { //int startPos = tokenSource.peek(-1).getStart(); //??? we lose source location for true start of !type - TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters,allowTypeVariableDeclarations)); + TypePattern p = new NotTypePattern(parseAtomicTypePattern(insideTypeParameters)); p = setAnnotationPatternForTypePattern(p,ap); return p; } if (maybeEat("(")) { - TypePattern p = parseTypePattern(insideTypeParameters,allowTypeVariableDeclarations); + TypePattern p = parseTypePattern(insideTypeParameters); p = setAnnotationPatternForTypePattern(p,ap); eat(")"); boolean isVarArgs = maybeEat("..."); @@ -614,7 +591,7 @@ public class PatternParser { return p; } int startPos = tokenSource.peek().getStart(); - TypePattern p = parseSingleTypePattern(insideTypeParameters,allowTypeVariableDeclarations); + TypePattern p = parseSingleTypePattern(insideTypeParameters); int endPos = tokenSource.peek(-1).getEnd(); p = setAnnotationPatternForTypePattern(p,ap); p.setLocation(sourceContext, startPos, endPos); @@ -688,34 +665,21 @@ public class PatternParser { } public TypePattern parseSingleTypePattern() { - return parseSingleTypePattern(false, false); + return parseSingleTypePattern(false); } - public TypePattern parseSingleTypePattern(boolean insideTypeParameters, boolean allowTypeVariableDeclarations) { + public TypePattern parseSingleTypePattern(boolean insideTypeParameters) { if (insideTypeParameters && maybeEat("?")) return parseGenericsWildcardTypePattern(); List names = parseDottedNamePattern(); - TypePattern upperBound = null; - TypePattern[] additionalInterfaceBounds = new TypePattern[0]; - TypePattern lowerBound = null; - if ((names.size() == 1) && allowTypeVariableDeclarations) { - if (maybeEatIdentifier("extends")) { - upperBound = parseTypePattern(false,false); - additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds(); - } - if (maybeEatIdentifier("super")) { - lowerBound = parseTypePattern(false,false); - } - } - int dim = 0; while (maybeEat("[")) { eat("]"); dim++; } - TypePatternList typeParameters = maybeParseTypeParameterList(allowTypeVariableDeclarations); + TypePatternList typeParameters = maybeParseTypeParameterList(); int endPos = tokenSource.peek(-1).getEnd(); boolean isVarArgs = maybeEat("..."); @@ -724,8 +688,7 @@ public class PatternParser { //??? what about the source location of any's???? if (names.size() == 1 && ((NamePattern)names.get(0)).isAny() && - dim == 0 && !isVarArgs && typeParameters == null && upperBound == null && - lowerBound == null) return TypePattern.ANY; + dim == 0 && !isVarArgs && typeParameters == null ) return TypePattern.ANY; // Notice we increase the dimensions if varargs is set. this is to allow type matching to // succeed later: The actual signature at runtime of a method declared varargs is an array type of @@ -733,8 +696,7 @@ public class PatternParser { // pattern 'Integer...' we create a WildTypePattern 'Integer[]' with varargs set. If this matches // during shadow matching, we confirm that the varargs flags match up before calling it a successful // match. - return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters, - upperBound,additionalInterfaceBounds,lowerBound); + return new WildTypePattern(names, includeSubtypes, dim+(isVarArgs?1:0), endPos,isVarArgs,typeParameters); } public TypePattern parseGenericsWildcardTypePattern() { @@ -744,11 +706,11 @@ public class PatternParser { TypePattern[] additionalInterfaceBounds = new TypePattern[0]; TypePattern lowerBound = null; if (maybeEatIdentifier("extends")) { - upperBound = parseTypePattern(false,false); + upperBound = parseTypePattern(false); additionalInterfaceBounds = maybeParseAdditionalInterfaceBounds(); } if (maybeEatIdentifier("super")) { - lowerBound = parseTypePattern(false,false); + lowerBound = parseTypePattern(false); } int endPos = tokenSource.peek(-1).getEnd(); return new WildTypePattern(names,false,0,endPos,false,null,upperBound,additionalInterfaceBounds,lowerBound); @@ -1070,7 +1032,7 @@ public class PatternParser { int startPos = tokenSource.peek().getStart(); AnnotationTypePattern annotationPattern = maybeParseAnnotationPattern(); ModifiersPattern modifiers = parseModifiersPattern(); - TypePattern returnType = parseTypePattern(false,true); + TypePattern returnType = parseTypePattern(false); TypePattern declaringType; NamePattern name = null; @@ -1088,7 +1050,7 @@ public class PatternParser { } else { kind = Member.METHOD; IToken nameToken = tokenSource.peek(); - declaringType = parseTypePattern(false,true); + declaringType = parseTypePattern(false); if (maybeEat(".")) { nameToken = tokenSource.peek(); name = parseNamePattern(); @@ -1207,11 +1169,11 @@ public class PatternParser { return tvs; } - public TypePatternList maybeParseTypeParameterList(boolean allowTypeVariables) { + public TypePatternList maybeParseTypeParameterList() { if (!maybeEat("<")) return null; List typePats = new ArrayList(); do { - TypePattern tp = parseTypePattern(true,allowTypeVariables); + TypePattern tp = parseTypePattern(true); typePats.add(tp); } while(maybeEat(",")); eat(">"); diff --git a/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java index ed0f0a5af..60e1e2d32 100644 --- a/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java +++ b/weaver/testsrc/org/aspectj/weaver/patterns/ParserTestCase.java @@ -301,39 +301,49 @@ public class ParserTestCase extends TestCase { public void testParseAnythingTypeVariable() { PatternParser parser = new PatternParser("?"); - WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false); + WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true); assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName()); } public void testParseAnythingExtendsTypeVariable() { PatternParser parser = new PatternParser("? extends Number"); - WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false); + WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true); assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName()); assertEquals("upper Bound of Number",new PatternParser("Number").parseTypePattern(),tp.getUpperBound()); } public void testParseAnythingSuperTypeVariable() { PatternParser parser = new PatternParser("? super Number+"); - WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true,false); + WildTypePattern tp = (WildTypePattern) parser.parseTypePattern(true); assertEquals("Expected type variable ?","?",tp.maybeGetSimpleName()); assertEquals("lower Bound of Number+",new PatternParser("Number+").parseTypePattern(),tp.getLowerBound()); } public void testParseDeclareParentsWithTypeParameterList() { - PatternParser parser = new PatternParser("declare parents<T> : Foo<T> implements IveGoneMad"); - DeclareParents decp = (DeclareParents) parser.parseDeclare(); - String[] tvp = decp.getTypeParameterNames(); - assertEquals("one type parameter",1,tvp.length); - assertEquals("expecting T","T",tvp[0]); + try { + PatternParser parser = new PatternParser("declare parents<T> : Foo<T> implements IveGoneMad"); + DeclareParents decp = (DeclareParents) parser.parseDeclare(); +// String[] tvp = decp.getTypeParameterNames(); +// assertEquals("one type parameter",1,tvp.length); +// assertEquals("expecting T","T",tvp[0]); + fail("Expecting parse exception"); + } catch (ParserException pEx) { + assertEquals(":",pEx.getMessage()); + } } public void testParameterizedTypePatternsAny() { - PatternParser parser = new PatternParser("*<T,S extends Number>"); - WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false,true); - TypePatternList tvs = wtp.getTypeParameters(); - assertEquals("2 type parameters",2,tvs.getTypePatterns().length); - assertEquals("T",new PatternParser("T").parseTypePattern(),tvs.getTypePatterns()[0]); - assertEquals("S extends Number",new PatternParser("S extends Number").parseTypePattern(false,true),tvs.getTypePatterns()[1]); + try { + PatternParser parser = new PatternParser("*<T,S extends Number>"); + WildTypePattern wtp = (WildTypePattern) parser.parseTypePattern(false); + // TypePatternList tvs = wtp.getTypeParameters(); + // assertEquals("2 type parameters",2,tvs.getTypePatterns().length); + // assertEquals("T",new PatternParser("T").parseTypePattern(),tvs.getTypePatterns()[0]); + // assertEquals("S extends Number",new PatternParser("S extends Number").parseTypePattern(false),tvs.getTypePatterns()[1]); + fail("Expecting parse exception"); + } catch (ParserException pEx) { + assertEquals(">",pEx.getMessage()); + } } public void testParameterizedTypePatternsSimple() { @@ -380,10 +390,15 @@ public class ParserTestCase extends TestCase { // test cases for pointcuts involving type variable specification. public void testParseCallPCDWithTypeVariables() { PatternParser parser = new PatternParser("call<T>(* Foo<T>.*(T))"); - Pointcut pc = parser.parsePointcut(); - String[] tvps = pc.getTypeVariablesInScope(); - assertEquals("1 type variable",1,tvps.length); - assertEquals("T",tvps[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvps = pc.getTypeVariablesInScope(); +// assertEquals("1 type variable",1,tvps.length); +// assertEquals("T",tvps[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testParseCallPCDWithIllegalBounds() { @@ -392,7 +407,7 @@ public class ParserTestCase extends TestCase { parser.parsePointcut(); fail("Expecting parse exception"); } catch (ParserException pEx) { - assertEquals("',' or '>'",pEx.getMessage()); + assertEquals("(",pEx.getMessage()); } } @@ -528,86 +543,136 @@ public class ParserTestCase extends TestCase { public void testExecutionWithTypeVariables() { PatternParser parser = new PatternParser("execution<T>(T Bar<T>.doSomething())"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testInitializationWithTypeVariables() { PatternParser parser = new PatternParser("initialization<T>(Bar<T>.new())"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testPreInitializationWithTypeVariables() { PatternParser parser = new PatternParser("preinitialization<T>(Bar<T>.new())"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testStaticInitializationWithTypeVariables() { PatternParser parser = new PatternParser("staticinitialization<T>(Bar<T>)"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testWithinWithTypeVariables() { PatternParser parser = new PatternParser("within<T>(Bar<T>)"); + try { Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + // String[] tvs = pc.getTypeVariablesInScope(); + // assertEquals("1 type pattern",1,tvs.length); + // assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testTypeParamList() { PatternParser parser = new PatternParser("Bar<T,S extends T, R extends S>"); - TypePattern tp = parser.parseTypePattern(false,true); - TypePattern[] tps = tp.getTypeParameters().getTypePatterns(); - assertEquals("3 type patterns",3,tps.length); - assertEquals("T",tps[0].toString()); - assertEquals("S",tps[1].toString()); - assertEquals("R",tps[2].toString()); + try { + TypePattern tp = parser.parseTypePattern(false); +// TypePattern[] tps = tp.getTypeParameters().getTypePatterns(); +// assertEquals("3 type patterns",3,tps.length); +// assertEquals("T",tps[0].toString()); +// assertEquals("S",tps[1].toString()); +// assertEquals("R",tps[2].toString()); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals(">",pEx.getMessage()); + } } public void testWithinCodeWithTypeVariables() { PatternParser parser = new PatternParser("withincode<T,S,R>(Bar<T,S extends T, R extends S>.new())"); + try { Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("3 type patterns",3,tvs.length); - assertEquals("T",tvs[0]); - assertEquals("S",tvs[1]); - assertEquals("R",tvs[2]); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("3 type patterns",3,tvs.length); +// assertEquals("T",tvs[0]); +// assertEquals("S",tvs[1]); +// assertEquals("R",tvs[2]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testCallWithTypeVariables() { PatternParser parser = new PatternParser("call<T>(* Bar<T>.*(..))"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testGetWithTypeVariables() { PatternParser parser = new PatternParser("get<T>(* Bar<T>.*)"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } public void testSetWithTypeVariables() { PatternParser parser = new PatternParser("set<T>(* Bar<T>.*)"); - Pointcut pc = parser.parsePointcut(); - String[] tvs = pc.getTypeVariablesInScope(); - assertEquals("1 type pattern",1,tvs.length); - assertEquals("T",tvs[0]); + try { + Pointcut pc = parser.parsePointcut(); +// String[] tvs = pc.getTypeVariablesInScope(); +// assertEquals("1 type pattern",1,tvs.length); +// assertEquals("T",tvs[0]); + fail("should have been a parse error"); + } catch (ParserException pEx) { + assertEquals("(",pEx.getMessage()); + } } |