167167// HashSet as the basis for the {a:a,b:this.$finals$.b} mapping listFinalVariables.
168168// This fixed all of the stream issues. See Test_Local, Test_java8, Test_Class.
169169
170+ // BH 2019.12.07 3.2.5-v2 fix for lambda expression with $$ must not be cached
170171// BH 2019.11.18 3.2.5-v0 fix for anonymous subclass of a local class not handling finals
171172// BH 2019.11.18 3.2.5-v0 fix for main method that throws exception not generating html test
172173// BH 2019.11.18 3.2.5-v0 fix for lambda expressions in classes with annotations
@@ -731,9 +732,10 @@ private String processLocalInstance(ASTNode node, ASTNode anonymousClassDeclarat
731732 // creation time and recover it here.
732733
733734 // String finals;
735+ boolean isStatic = true ;
734736 if (localType != REALLY_LOCAL_CLASS ) {
735737 // lambda and anonymous classes are defined inline.
736- addInnerDeclaration (anonymousClassDeclaration == null ? node : anonymousClassDeclaration , binding ,
738+ isStatic = addInnerDeclaration (anonymousClassDeclaration == null ? node : anonymousClassDeclaration , binding ,
737739 lambdaType , false , null );
738740 }
739741 IMethodBinding constructorDeclaration ;
@@ -762,7 +764,7 @@ private String processLocalInstance(ASTNode node, ASTNode anonymousClassDeclarat
762764 class_localType = oldLocalType ;
763765 if (lambdaType != LAMBDA_METHOD && localType != REALLY_LOCAL_CLASS )
764766 buffer .append (")" ); // end of line (..., ...)
765- return (package_htClassKeyToVisitedFinalVars .get (binding .getKey ()).isEmpty () ? anonName : null );
767+ return (isStatic && package_htClassKeyToVisitedFinalVars .get (binding .getKey ()).isEmpty () ? anonName : null );
766768 }
767769
768770 /**
@@ -775,17 +777,18 @@ private String processLocalInstance(ASTNode node, ASTNode anonymousClassDeclarat
775777 * @param isTrulyLocal not anonymous and not lambda -- private to a method
776778 * @param bodyDeclarations
777779 */
778- private void addInnerDeclaration (ASTNode node , ITypeBinding binding , int lambdaType , boolean isTrulyLocal ,
780+ private boolean addInnerDeclaration (ASTNode node , ITypeBinding binding , int lambdaType , boolean isTrulyLocal ,
779781 List <?> bodyDeclarations ) {
780782
783+ boolean isStatic = true ;
781784 boolean wasAnonymous = class_isAnonymousOrLocal ;
782785 String key = binding .getKey ();
783786 class_isAnonymousOrLocal = true ;
784787 Set <IVariableBinding > lastVisitedVars = class_visitedFinalVars ;
785788 Set <IVariableBinding > myVisitedVars = class_visitedFinalVars = new HashSet <>();
786789 package_htClassKeyToVisitedFinalVars .put (key , myVisitedVars );
787790 if (lambdaType != NOT_LAMBDA ) {
788- addClassOrInterface (node , binding , null , 'm' );
791+ isStatic = addClassOrInterface (node , binding , null , 'm' );
789792 if (lambdaType == LAMBDA_METHOD )
790793 buffer .append ("); return " );
791794 else
@@ -807,10 +810,9 @@ private void addInnerDeclaration(ASTNode node, ITypeBinding binding, int lambdaT
807810 }
808811 class_visitedFinalVars = lastVisitedVars ;
809812 class_isAnonymousOrLocal = wasAnonymous ;
813+ return isStatic ;
810814 }
811815
812- static int test = 0 ;
813-
814816
815817 /**
816818 * Generated final variable list for anonymous class creation. Update the
@@ -1158,7 +1160,7 @@ public boolean visit(MethodInvocation node) {
11581160 * @param mBinding
11591161 * @param expression
11601162 */
1161- private void addMethodInvocation (SimpleName javaQualifier , List <?> arguments , IMethodBinding mBinding ,
1163+ private boolean addMethodInvocation (SimpleName javaQualifier , List <?> arguments , IMethodBinding mBinding ,
11621164 Expression expression , int lambdaArity ) {
11631165 if (javaQualifier == null ) {
11641166 // not possible?
@@ -1259,23 +1261,24 @@ private void addMethodInvocation(SimpleName javaQualifier, List<?> arguments, IM
12591261 //
12601262 boolean classIsTarget = (class_localType == LAMBDA_WRAPPED && (
12611263 (isStatic
1262- || isVariableBinding (expression )
12631264 || expression instanceof ClassInstanceCreation
1265+ || isVariableBinding (expression )
12641266 || expression instanceof ThisExpression
12651267 || "java.lang.Class" .equals (removeBracketsAndFixNullPackageName (declaringClassJavaClassName )) // String.class::cast
12661268 ) // BH Added 2019.05.13
12671269 && lambdaArity == mBinding .getParameterTypes ().length ));
12681270
1269- // ////bufferDebug("addmeth isclasstarget " + isStatic + " "+ classIsTarget
1270- // + " " + (expression == null ? null : expression.getClass().getName())
1271+ //bufferDebug("addmeth isclasstarget " + isStatic + " classIsTarget="+ classIsTarget
1272+ // + " ivarbinding=" +isVariableBinding(expression) + " exp=" + (expression == null ?
1273+ // null : expression.getClass().getName())
12711274// + " " + declaringClassJavaClassName
12721275// );
12731276 String opening = (classIsTarget ? "$$." : "t." ) + finalMethodNameWith$Params + ".apply("
12741277 + (isStatic ? "null" : classIsTarget ? "$$" : "t" ) + ",[" ;
12751278 buffer .append (opening );
12761279 buffer .append (getLambdaParamList (mBinding , lambdaArity ));
12771280 buffer .append ("])" );
1278- return ;
1281+ return isStatic ;
12791282 }
12801283 if (finalMethodNameWith$Params .indexOf ('|' ) >= 0 ) {
12811284 // cover multiple parameter options to cover older versions of java
@@ -1310,6 +1313,7 @@ private void addMethodInvocation(SimpleName javaQualifier, List<?> arguments, IM
13101313 buffer .append ("(" );
13111314 addMethodParameterList (arguments , mBinding , null , null , isIndexOf ? METHOD_INDEXOF : METHOD_NOTSPECIAL );
13121315 buffer .append (term );
1316+ return true ;
13131317 }
13141318
13151319 /**
@@ -1466,31 +1470,18 @@ public boolean visit(TryStatement node) {
14661470 List <CatchClause > catchClauses = node .catchClauses ();
14671471 int size = catchClauses .size ();
14681472 Block finallyBlock = node .getFinally ();
1469- buffer .append (size > 0 || finallyBlock != null ? "try " : "/*try*/ " );
14701473 List <ASTNode > resources = node .resources ();
14711474 // Returns the live ordered list of resources for this try statement (added in
14721475 // JLS4 API).
14731476 // [ooh...JSL9 change...]
14741477 // A resource is either a VariableDeclarationExpression or (since JLS9) a Name.
1475-
1476- int pt = (resources == null || resources .size () == 0 ? -1 : buffer .length ());
1477- node .getBody ().accept (this );
1478- if (pt >= 0 ) {
1479- // just after first "{"
1480- String buf = buffer .substring ((pt = buffer .indexOf ("{" , pt ) + 1 ));
1481- buffer .setLength (pt );
1482- for (int i = 0 ; i < resources .size (); i ++) {
1483- ASTNode resource = resources .get (i );
1484- if (resource instanceof VariableDeclarationExpression ) {
1485- resource .accept (this );
1486- buffer .append (";" );
1487- } else {
1488- // Java 9 -- just a Name.
1489- buffer .append ("/* Java 9 resource " + resource + "*/\r \n " );
1490- }
1491- }
1492- buffer .append (buf );
1478+ int pt = -1 ;
1479+ if (resources != null && resources .size () > 0 ) {
1480+ buffer .append ("try {\r \n " );
1481+ pt = buffer .length ();
14931482 }
1483+ buffer .append (size > 0 || finallyBlock != null ? "try " : "/*try*/ " );
1484+ node .getBody ().accept (this );
14941485 if (size > 0 ) {
14951486 String catchEName = "e$$" ;
14961487 if (size == 1 ) {
@@ -1554,11 +1545,38 @@ public boolean visit(TryStatement node) {
15541545 if (finallyBlock != null ) {
15551546 buffer .append (" finally " );
15561547 finallyBlock .accept (this );
1548+ }
1549+ if (pt >= 0 ) {
1550+ // just after first "{"
1551+ String buf = buffer .substring (pt );
1552+ buffer .setLength (pt );
1553+ String closing = "" ;
1554+ for (int i = 0 ; i < resources .size (); i ++) {
1555+ ASTNode resource = resources .get (i );
1556+ pt = buffer .length ();
1557+ resource .accept (this );
1558+ buffer .append (";\r \n " );
1559+ closing = getResourceClosing (pt ) + closing ;
1560+ }
1561+ buffer .append (buf );
1562+ buffer .append ("\r \n }finally{/*res*/" ).append (closing ).append ("}" );
15571563 }
15581564 buffer .append ("\r \n " );
15591565 return false ;
15601566 }
15611567
1568+ private String getResourceClosing (int pt ) {
1569+ String name = buffer .substring (pt );
1570+ // Java 9 try(res) or Java 8 try(OutputStream os = ....)
1571+ if ((pt = name .indexOf ("=" )) >= 0 ||
1572+ (pt = name .indexOf (";" )) >= 0 ) {
1573+ name = name .substring (0 , pt );
1574+ }
1575+ if (name .startsWith ("var " ))
1576+ name = name .substring (4 );
1577+ return "\r \n try{" + name + "&&" + name + ".close$&&" + name + ".close$()}catch(_){}" ;
1578+ }
1579+
15621580 /**
15631581 * A class or interface is being declared.
15641582 *
@@ -1652,9 +1670,9 @@ private void appendClinit() {
16521670 * @return localName
16531671 */
16541672 @ SuppressWarnings ({ "null" , "unchecked" })
1655- private void addClassOrInterface (ASTNode node , ITypeBinding binding , List <?> bodyDeclarations , char type ) {
1673+ private boolean addClassOrInterface (ASTNode node , ITypeBinding binding , List <?> bodyDeclarations , char type ) {
16561674 if (binding == null )
1657- return ;
1675+ return false ;
16581676
16591677 checkGenericClass (binding , binding );
16601678
@@ -1712,7 +1730,7 @@ private void addClassOrInterface(ASTNode node, ITypeBinding binding, List<?> bod
17121730
17131731 trailingBuffer .append (tempVisitor .buffer .toString ());
17141732
1715- return ;
1733+ return false ;
17161734 }
17171735
17181736 // set up key fields and local variables
@@ -1743,9 +1761,18 @@ private void addClassOrInterface(ASTNode node, ITypeBinding binding, List<?> bod
17431761 finalShortClassName = finalShortClassName .substring (3 );
17441762 }
17451763 setClassAndBinding (finalShortClassName , binding );
1746- if (isLambda )
1764+ if (isLambda ) {
17471765 buffer .append ("(" );
1748- buffer .append ("(P$." + finalShortClassName + "||" );
1766+
1767+
1768+ // problem here 2019.12.07 cifbinary was that $$-wrapped lambda methods must NOT be reused.
1769+ //bufferDebug("addcoi " + isLambda + " " + class_localType);
1770+
1771+
1772+ }
1773+ buffer .append ("(" );
1774+ if (!isLambda || class_localType != LAMBDA_WRAPPED )
1775+ buffer .append ("P$." + finalShortClassName + "||" );
17491776 finalPackageName = "P$" ;
17501777 } else {
17511778 // Top or inner named classes are already set.
@@ -2071,8 +2098,9 @@ && checkAnnotations(element, CHECK_J2S_IGNORE_AND_ANNOTATIONS)) {
20712098
20722099 StringBuffer defaults = new StringBuffer ();
20732100
2101+ boolean isStatic = true ;
20742102 if (isLambda ) {
2075- addLambdaClass (node , binding .getFunctionalInterfaceMethod ());
2103+ isStatic = addLambdaClass (node , binding .getFunctionalInterfaceMethod ());
20762104 } else {
20772105 for (Iterator <?> iter = bodyDeclarations .iterator (); iter .hasNext ();) {
20782106 ASTNode element = (ASTNode ) iter .next ();
@@ -2171,6 +2199,7 @@ && checkAnnotations(element, CHECK_J2S_IGNORE_AND_ANNOTATIONS)) {
21712199 setClassAndBinding (oldShortClassName , oldBinding );
21722200 }
21732201 }
2202+ return isStatic ;
21742203 }
21752204
21762205// private boolean checkDeclarationType(BodyDeclaration element, int type) {
@@ -6848,7 +6877,8 @@ private boolean addLambdaMethodReference(MethodReference node, Expression exp) {
68486877 buffer .append ("})(" );
68496878 appendFinalMethodQualifier (exp , declaringClass , null , FINAL_ESCAPECACHE | FINAL_LAMBDA );
68506879 buffer .append (")" );
6851- addLambdaReuse (pt , anonName );
6880+ if (anonName != null )
6881+ addLambdaReuse (pt , anonName );
68526882 return false ;
68536883 }
68546884
@@ -6861,6 +6891,9 @@ private boolean addLambdaMethodReference(MethodReference node, Expression exp) {
68616891 private void addLambdaReuse (int pt , String anonName ) {
68626892 String tmp = buffer .substring (pt );
68636893 buffer .setLength (pt );
6894+
6895+ // bufferDebug("addLambdaReuse " + anonName);
6896+
68646897 anonName = getFinalJ2SClassName (anonName , FINAL_P );
68656898 buffer .append ("(" + anonName + "$||(" + anonName + "$=(" )
68666899 .append (tmp ).append (")))" );
@@ -6894,7 +6927,7 @@ private String getLambdaParamList(IMethodBinding mBinding, int arity0) {
68946927 * @param lnode
68956928 * @param mBinding
68966929 */
6897- private void addLambdaClass (ASTNode lnode , IMethodBinding mBinding ) {
6930+ private boolean addLambdaClass (ASTNode lnode , IMethodBinding mBinding ) {
68986931 if (lnode instanceof LambdaExpression ) {
68996932 buffer .append ("/*lambda_E*/" );
69006933 LambdaExpression node = (LambdaExpression ) lnode ;
@@ -6907,7 +6940,7 @@ private void addLambdaClass(ASTNode lnode, IMethodBinding mBinding) {
69076940 processMethodDeclaration (mBinding , params , node .getBody (), false , LAMBDA_EXPRESSION );
69086941 ////bufferDebug("procmethoddecl2");
69096942 class_localType = localType ;
6910- return ;
6943+ return true ;
69116944 }
69126945 if (lnode instanceof CreationReference ) {
69136946 buffer .append ("/*lambda_C*/" );
@@ -6923,7 +6956,7 @@ private void addLambdaClass(ASTNode lnode, IMethodBinding mBinding) {
69236956 addConstructor (binding , mBinding , null , mBinding .getParameterTypes ().length );
69246957 }
69256958 buffer .append ("});\r \n " );
6926- return ;
6959+ return true ;
69276960 }
69286961 // method of one type or another
69296962 SimpleName identifier ;
@@ -6951,11 +6984,12 @@ private void addLambdaClass(ASTNode lnode, IMethodBinding mBinding) {
69516984 } else {
69526985 buffer .append ("/*lambda_?*/" );
69536986 log ("??? addLambdaMethod " + lnode .getClass ().getName ());
6954- return ;
6987+ return false ;
69556988 }
69566989 processMethodDeclaration (mBinding , null , null , false , LAMBDA_METHOD );
6957- addMethodInvocation (identifier , null , mBinding1 , exp , mBinding .getParameterTypes ().length );
6990+ boolean isStatic = addMethodInvocation (identifier , null , mBinding1 , exp , mBinding .getParameterTypes ().length );
69586991 buffer .append ("});\r \n " );
6992+ return isStatic ;
69596993 }
69606994
69616995 /**
0 commit comments