114114 * non-static {@code SimpleMethodCall}s and {@code SimpleFieldAccess}es.</li>
115115 * <li>CONSTRUCTOR on {@code ConstructorCall}s and all allocations: {@code SimpleAllocation}s,
116116 * {@code InnerAllocation}s, {@code AnonymousAllocation}s, and {@code AnonymousInnerAllocation}s</li>
117+ * <li>ENCLOSING_THIS on {@code SimpleAllocation}s and {@code AnonymousAllocations}s that represent
118+ * inner allocations with a "this" value of the given class as the enclosing object</li>
117119 * <li>FIELD on all {@code FieldAccess}es</li>
118120 * <li>METHOD on all {@code MethodCall}s</li>
119121 * <li>VARIABLE on all {@code VariableAccess}es, {@code VariableDeclarations}, and {@code FormalParameters}</li>
@@ -204,9 +206,10 @@ public void checkConstructorCall(ConstructorCall node) {
204206 catch (InvalidTypeArgumentException e ) {
205207 throw new ExecutionError ("type.argument" , node );
206208 }
207- catch (TypeSystemException e ) {
209+ catch (UnmatchedLookupException e ) {
208210 setErrorStrings (node , ts .userRepresentation (type ), nodeTypesString (args ));
209- throw new ExecutionError ("no.such.constructor" , node );
211+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.constructor" , node ); }
212+ else { throw new ExecutionError ("no.such.constructor" , node ); }
210213 }
211214 }
212215
@@ -217,7 +220,7 @@ public void checkAccessibility(Access.Limited symbol, Node node) {
217220
218221 /**
219222 * Verify that the given symbol is accessible. If {@code alwaysCheckPrivate}, private access is
220- * checked even when the options dictate otherwise.
223+ * checked even when the options dictate otherwise. Assumes symbol is not an anonymous class.
221224 */
222225 private void checkAccessibility (Access .Limited symbol , Node node , boolean alwaysCheckPrivate ) {
223226 switch (symbol .accessibility ()) {
@@ -352,7 +355,6 @@ else if (context.fieldExists(first.image(), ts)) {
352355 }
353356 }
354357 catch (AmbiguousNameException e ) { throw new ExecutionError ("ambiguous.name" , node ); }
355- catch (InvalidTargetException e ) { throw new RuntimeException ("context produced bad type" ); }
356358 catch (InvalidTypeArgumentException e ) { throw new ExecutionError ("type.argument.arity" , node ); }
357359 catch (UnmatchedLookupException e ) {
358360 if (e .matches () == 0 ) { throw new ExecutionError ("undefined.name.noinfo" , node ); }
@@ -375,7 +377,6 @@ else if (ts.containsClass(classType, memberName.image())) {
375377 checkAccessibility (memberType .ofClass (), node );
376378 classType = memberType ;
377379 }
378- catch (InvalidTargetException e ) { throw new RuntimeException ("ts.containsClass lied" ); }
379380 catch (InvalidTypeArgumentException e ) { throw new ExecutionError ("type.argument.arity" , node ); }
380381 catch (UnmatchedLookupException e ) {
381382 if (e .matches () == 0 ) { throw new ExecutionError ("undefined.name.noinfo" , node ); }
@@ -482,7 +483,6 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
482483 return setType (node , result );
483484 }
484485 catch (AmbiguousNameException e ) { throw new ExecutionError ("ambiguous.name" , node ); }
485- catch (InvalidTargetException e ) { throw new RuntimeException ("context produced bad type" ); }
486486 catch (UnmatchedLookupException e ) {
487487 if (e .matches () == 0 ) { throw new ExecutionError ("undefined.name.noinfo" , node ); }
488488 else { throw new ExecutionError ("ambiguous.name" , node ); }
@@ -506,9 +506,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
506506 addRuntimeCheck (node , result , ref .field ().type ());
507507 return setType (node , result );
508508 }
509- catch (TypeSystemException e ) {
509+ catch (UnmatchedLookupException e ) {
510510 setErrorStrings (node , ts .userRepresentation (receiverT ), node .getFieldName ());
511- throw new ExecutionError ("no.such.field" , node );
511+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.field" , node ); }
512+ else { throw new ExecutionError ("no.such.field" , node ); }
512513 }
513514 }
514515
@@ -534,9 +535,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
534535 addRuntimeCheck (node , result , ref .field ().type ());
535536 return setType (node , result );
536537 }
537- catch (TypeSystemException e ) {
538+ catch (UnmatchedLookupException e ) {
538539 setErrorStrings (node , ts .userRepresentation (t ), node .getFieldName ());
539- throw new ExecutionError ("no.such.field" , node );
540+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.field" , node ); }
541+ else { throw new ExecutionError ("no.such.field" , node ); }
540542 }
541543 }
542544
@@ -555,9 +557,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
555557 addRuntimeCheck (node , result , ref .field ().type ());
556558 return setType (node , result );
557559 }
558- catch (TypeSystemException e ) {
560+ catch (UnmatchedLookupException e ) {
559561 setErrorStrings (node , ts .userRepresentation (t ), node .getFieldName ());
560- throw new ExecutionError ("no.such.static.field" , node );
562+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.field" , node ); }
563+ else { throw new ExecutionError ("no.such.static.field" , node ); }
561564 }
562565 }
563566
@@ -612,9 +615,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
612615 catch (InvalidTypeArgumentException e ) {
613616 throw new ExecutionError ("type.argument" , node );
614617 }
615- catch (TypeSystemException e ) {
618+ catch (UnmatchedLookupException e ) {
616619 setErrorStrings (node , ts .userRepresentation (t ), node .getMethodName (), nodeTypesString (args ));
617- throw new ExecutionError ("no.such.method" , node );
620+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.method" , node ); }
621+ else { throw new ExecutionError ("no.such.method" , node ); }
618622 }
619623 }
620624
@@ -672,9 +676,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
672676 catch (InvalidTypeArgumentException e ) {
673677 throw new ExecutionError ("type.argument" , node );
674678 }
675- catch (TypeSystemException e ) {
679+ catch (UnmatchedLookupException e ) {
676680 setErrorStrings (node , ts .userRepresentation (receiverT ), node .getMethodName (), nodeTypesString (args ));
677- throw new ExecutionError ("no.such.method" , node );
681+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.method" , node ); }
682+ else { throw new ExecutionError ("no.such.method" , node ); }
678683 }
679684 }
680685
@@ -714,9 +719,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
714719 catch (InvalidTypeArgumentException e ) {
715720 throw new ExecutionError ("type.argument" , node );
716721 }
717- catch (TypeSystemException e ) {
722+ catch (UnmatchedLookupException e ) {
718723 setErrorStrings (node , ts .userRepresentation (t ), node .getMethodName (), nodeTypesString (args ));
719- throw new ExecutionError ("no.such.method" , node );
724+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.method" , node ); }
725+ else { throw new ExecutionError ("no.such.method" , node ); }
720726 }
721727 }
722728
@@ -750,9 +756,10 @@ private DJClass resolveThis(Option<String> outerName, Node node) {
750756 catch (InvalidTypeArgumentException e ) {
751757 throw new ExecutionError ("type.argument" , node );
752758 }
753- catch (TypeSystemException e ) {
759+ catch (UnmatchedLookupException e ) {
754760 setErrorStrings (node , ts .userRepresentation (t ), node .getMethodName (), nodeTypesString (args ));
755- throw new ExecutionError ("no.such.static.method" , node );
761+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.method" , node ); }
762+ else { throw new ExecutionError ("no.such.method" , node ); }
756763 }
757764 }
758765
@@ -835,10 +842,13 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
835842 */
836843 @ Override public Type visit (SimpleAllocation node ) {
837844 Type t = checkTypeName (node .getCreationType ());
838- // TODO: Allow a simple allocation of a dynamic inner class defined in the current context
839- // (where "new Inner()" is the equivalent of "this.new Inner()" or "SomeOuter.this.new Inner()")
840- if (!ts .isConcrete (t ) || !ts .isStatic (t )) {
841- throw new ExecutionError ("allocation.type" , node );
845+ if (!ts .isConcrete (t )) { throw new ExecutionError ("allocation.type" , node ); }
846+
847+ Option <Type > dynamicOuter = ts .dynamicallyEnclosingType (t );
848+ if (dynamicOuter .isSome ()) {
849+ DJClass enclosingThis = enclosingThis (dynamicOuter .unwrap ());
850+ if (enclosingThis == null ) { throw new ExecutionError ("allocation.type" , node ); }
851+ else { setEnclosingThis (node , enclosingThis ); }
842852 }
843853
844854 Iterable <? extends Expression > args = node .getArguments ();
@@ -860,9 +870,10 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
860870 catch (InvalidTypeArgumentException e ) {
861871 throw new ExecutionError ("type.argument" , node );
862872 }
863- catch (TypeSystemException e ) {
873+ catch (UnmatchedLookupException e ) {
864874 setErrorStrings (node , ts .userRepresentation (t ), nodeTypesString (args ));
865- throw new ExecutionError ("no.such.constructor" , node );
875+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.constructor" , node ); }
876+ else { throw new ExecutionError ("no.such.constructor" , node ); }
866877 }
867878 }
868879
@@ -872,11 +883,17 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
872883 */
873884 @ Override public Type visit (AnonymousAllocation node ) {
874885 Type t = checkTypeName (node .getCreationType ());
875- // TODO: Allow a simple allocation of a dynamic inner class defined in the current context (as above)
876- if (!ts .isStatic (t ) || (!ts .isExtendable (t ) && !ts .isImplementable (t ))) {
886+ if (!ts .isExtendable (t ) && !ts .isImplementable (t )) {
877887 throw new ExecutionError ("allocation.type" , node );
878888 }
879889
890+ Option <Type > dynamicOuter = ts .dynamicallyEnclosingType (t );
891+ if (dynamicOuter .isSome ()) {
892+ DJClass enclosingThis = enclosingThis (dynamicOuter .unwrap ());
893+ if (enclosingThis == null ) { throw new ExecutionError ("allocation.type" , node ); }
894+ else { setEnclosingThis (node , enclosingThis ); }
895+ }
896+
880897 Iterable <? extends Expression > args = node .getArguments ();
881898 checkList (args );
882899
@@ -896,9 +913,10 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
896913 catch (InvalidTypeArgumentException e ) {
897914 throw new ExecutionError ("type.argument" , node );
898915 }
899- catch (TypeSystemException e ) {
916+ catch (UnmatchedLookupException e ) {
900917 setErrorStrings (node , ts .userRepresentation (t ), nodeTypesString (args ));
901- throw new ExecutionError ("no.such.constructor" , node );
918+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.constructor" , node ); }
919+ else { throw new ExecutionError ("no.such.constructor" , node ); }
902920 }
903921 }
904922
@@ -914,6 +932,19 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
914932 return setType (node , ts .makeClassType (c ));
915933 }
916934
935+ /**
936+ * Determine the innermost "this" class that can be used as an allocation's enclosing object
937+ * where the given type is expected. May return {@code null} if none is found.
938+ */
939+ private DJClass enclosingThis (Type expected ) {
940+ DJClass candidate = context .getThis ();
941+ while (candidate != null ) {
942+ if (ts .isSubtype (SymbolUtil .thisType (candidate ), expected )) { return candidate ; }
943+ candidate = SymbolUtil .dynamicOuterClass (candidate );
944+ }
945+ return null ;
946+ }
947+
917948 /**
918949 * Visits a InnerAllocation. JLS 15.9.
919950 * @return The type of the expression
@@ -956,17 +987,19 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
956987 catch (InvalidTypeArgumentException e ) {
957988 throw new ExecutionError ("type.argument" , node );
958989 }
959- catch (TypeSystemException e ) {
990+ catch (UnmatchedLookupException e ) {
960991 setErrorStrings (node , ts .userRepresentation (t ), nodeTypesString (args ));
961- throw new ExecutionError ("no.such.constructor" , node );
992+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.constructor" , node ); }
993+ else { throw new ExecutionError ("no.such.constructor" , node ); }
962994 }
963995 }
964996 catch (InvalidTypeArgumentException e ) {
965997 throw new ExecutionError ("type.argument" , node );
966998 }
967- catch (TypeSystemException e ) {
999+ catch (UnmatchedLookupException e ) {
9681000 setErrorStrings (node , ts .userRepresentation (enclosing ), node .getClassName ());
969- throw new ExecutionError ("no.such.inner.class" , node );
1001+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.inner.class" , node ); }
1002+ else { throw new ExecutionError ("no.such.inner.class" , node ); }
9701003 }
9711004 }
9721005
@@ -1011,17 +1044,19 @@ private void addRuntimeCheck(Node node, Type expectedType, Type declaredActualTy
10111044 catch (InvalidTypeArgumentException e ) {
10121045 throw new ExecutionError ("type.argument" , node );
10131046 }
1014- catch (TypeSystemException e ) {
1047+ catch (UnmatchedLookupException e ) {
10151048 setErrorStrings (node , ts .userRepresentation (t ), nodeTypesString (args ));
1016- throw new ExecutionError ("no.such.constructor" , node );
1049+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.constructor" , node ); }
1050+ else { throw new ExecutionError ("no.such.constructor" , node ); }
10171051 }
10181052 }
10191053 catch (InvalidTypeArgumentException e ) {
10201054 throw new ExecutionError ("type.argument" , node );
10211055 }
1022- catch (TypeSystemException e ) {
1056+ catch (UnmatchedLookupException e ) {
10231057 setErrorStrings (node , ts .userRepresentation (enclosing ), node .getClassName ());
1024- throw new ExecutionError ("no.such.inner.class" , node );
1058+ if (e .matches () > 1 ) { throw new ExecutionError ("ambiguous.inner.class" , node ); }
1059+ else { throw new ExecutionError ("no.such.inner.class" , node ); }
10251060 }
10261061
10271062 TreeClassLoader loader = new TreeClassLoader (context .getClassLoader (), opt );
0 commit comments