From e53ce0d34818304c8d5bb87e26a352d96b42300d Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Tue, 28 Feb 2023 14:29:44 +0100 Subject: [PATCH 01/32] [maven-release-plugin] prepare for next development iteration --- javaparser-core-generators/pom.xml | 2 +- javaparser-core-metamodel-generator/pom.xml | 2 +- javaparser-core-serialization/pom.xml | 2 +- javaparser-core-testing-bdd/pom.xml | 2 +- javaparser-core-testing/pom.xml | 2 +- javaparser-core/pom.xml | 2 +- javaparser-symbol-solver-core/pom.xml | 2 +- javaparser-symbol-solver-testing/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/javaparser-core-generators/pom.xml b/javaparser-core-generators/pom.xml index a97e295039..33fc2aaf44 100644 --- a/javaparser-core-generators/pom.xml +++ b/javaparser-core-generators/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-core-metamodel-generator/pom.xml b/javaparser-core-metamodel-generator/pom.xml index f33f9c5511..6a65bbd868 100644 --- a/javaparser-core-metamodel-generator/pom.xml +++ b/javaparser-core-metamodel-generator/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-core-serialization/pom.xml b/javaparser-core-serialization/pom.xml index c4320c954d..43456b3ee2 100644 --- a/javaparser-core-serialization/pom.xml +++ b/javaparser-core-serialization/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-core-testing-bdd/pom.xml b/javaparser-core-testing-bdd/pom.xml index 56bba83b76..7f5637519a 100644 --- a/javaparser-core-testing-bdd/pom.xml +++ b/javaparser-core-testing-bdd/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-core-testing/pom.xml b/javaparser-core-testing/pom.xml index 64a49f5a72..820b0cf3c7 100644 --- a/javaparser-core-testing/pom.xml +++ b/javaparser-core-testing/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-core/pom.xml b/javaparser-core/pom.xml index 14ab1906c2..7b5b43662a 100644 --- a/javaparser-core/pom.xml +++ b/javaparser-core/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-symbol-solver-core/pom.xml b/javaparser-symbol-solver-core/pom.xml index 9226208814..2260ff511c 100644 --- a/javaparser-symbol-solver-core/pom.xml +++ b/javaparser-symbol-solver-core/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/javaparser-symbol-solver-testing/pom.xml b/javaparser-symbol-solver-testing/pom.xml index fc5617bdb1..e201e0504d 100644 --- a/javaparser-symbol-solver-testing/pom.xml +++ b/javaparser-symbol-solver-testing/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.1 + 3.25.2-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 2fb6cc8cc4..e5cdfae1f0 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.github.javaparser javaparser-parent pom - 3.25.1 + 3.25.2-SNAPSHOT javaparser-parent https://github.com/javaparser From 2d7ff719fbe7bd0ec2307c4b82aa66d0e3e3cbf3 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Tue, 28 Feb 2023 18:41:17 +0100 Subject: [PATCH 02/32] Fix: issue 3919 An array of primitive type cannot be assigned to an array of object --- .../javaparser/resolution/types/ResolvedArrayType.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java index 657d4413ce..15dcff5bf7 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java @@ -94,11 +94,10 @@ public boolean isAssignableBy(ResolvedType other) { if (baseType.isPrimitive() && other.asArrayType().getComponentType().isPrimitive()) { return baseType.equals(other.asArrayType().getComponentType()); } - // an array of Object is assignable by any array of primitive type - // but an array of primitive type is not assignable by an array of boxed type nor the reverse - if (!isJavaLangObject(baseType) - && ((baseType.isPrimitive() && other.asArrayType().getComponentType().isReferenceType()) - || (baseType.isReferenceType() && other.asArrayType().getComponentType().isPrimitive()))) { + // An array of primitive type is not assignable by an array of boxed type nor the reverse + // An array of primitive type cannot be assigned to an array of Object + if ((baseType.isPrimitive() && other.asArrayType().getComponentType().isReferenceType()) + || (baseType.isReferenceType() && other.asArrayType().getComponentType().isPrimitive())) { return false; } // An array can be assigned only to a variable of a compatible array type, or to From d920214efb1ea6cfd417ac2b4560430e23410f78 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Tue, 28 Feb 2023 18:43:22 +0100 Subject: [PATCH 03/32] Add unit tests --- .../resolution/types/ResolvedArrayTypeTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java index 2e7b98ec67..1dd8da7801 100755 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java @@ -164,6 +164,18 @@ void isNotAssignableWithreference() { // An array of primitive type cannot be assigned to a Boxed type variable, // because Boxed type is a class type other than Object assertFalse(array(ResolvedPrimitiveType.LONG).isAssignableBy(rLong)); + assertTrue(array(rObject).isAssignableBy(array(rLong))); + assertFalse(array(rObject).isAssignableBy(array(ResolvedPrimitiveType.LONG))); + } + + @Test + void ArrayOfObjectIsAssignableByArrayOfReference() { + assertTrue(array(rObject).isAssignableBy(array(rLong))); + } + + @Test + void ArrayOfObjectIsNotAssignableByArrayOfPrimitiveType() { + assertFalse(array(rObject).isAssignableBy(array(ResolvedPrimitiveType.LONG))); } private boolean isAssignableBy(ResolvedType type, ResolvedType... types) { From 6ac5b8a092230570ab847de7aac176228c2a5333 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Wed, 1 Mar 2023 10:18:20 +0100 Subject: [PATCH 04/32] Fix the method resolution logic by better handling the variable arity methods in the case where the last parameter of the expected method is an array of objects and the actual parameter is an array --- .../logic/MethodResolutionLogic.java | 29 +++++++++++++++++-- .../resolution/types/ResolvedArrayType.java | 4 --- .../types/ResolvedArrayTypeTest.java | 29 +++++++++---------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java index f098df04ef..9b68c78bf3 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/MethodResolutionLogic.java @@ -50,7 +50,7 @@ private static List groupVariadicParamValues(List ar res.add(variadicType); } else { ResolvedType componentType = findCommonType(variadicValues); - res.add(new ResolvedArrayType(componentType)); + res.add(convertToVariadicParameter(componentType)); } return res; } @@ -149,8 +149,21 @@ private static boolean isApplicable(ResolvedMethodDeclaration methodDeclaration, continue; } + // if this is a variable arity method and we are trying to evaluate the last parameter + // then we consider that an array of objects can be assigned by any array + // for example: + // The method call expression String.format("%d", new int[] {1}) + // must refer to the method String.format(String, Object...) + // even if an array of primitive type cannot be assigned to an array of Object + if (methodDeclaration.getParam(i).isVariadic() + && (i == countOfMethodParametersDeclared - 1) + && isArrayOfObject(expectedDeclaredType) + && actualArgumentType.isArray()) { + continue; + } + boolean isAssignableWithoutSubstitution = expectedDeclaredType.isAssignableBy(actualArgumentType) || - (methodDeclaration.getParam(i).isVariadic() && new ResolvedArrayType(expectedDeclaredType).isAssignableBy(actualArgumentType)); + (methodDeclaration.getParam(i).isVariadic() && convertToVariadicParameter(expectedDeclaredType).isAssignableBy(actualArgumentType)); if (!isAssignableWithoutSubstitution && expectedDeclaredType.isReferenceType() && actualArgumentType.isReferenceType()) { isAssignableWithoutSubstitution = isAssignableMatchTypeParameters( @@ -178,7 +191,7 @@ private static boolean isApplicable(ResolvedMethodDeclaration methodDeclaration, continue; } if (methodIsDeclaredWithVariadicParameter && i == countOfMethodParametersDeclared - 1) { - if (new ResolvedArrayType(expectedDeclaredType).isAssignableBy(actualArgumentType)) { + if (convertToVariadicParameter(expectedDeclaredType).isAssignableBy(actualArgumentType)) { continue; } } @@ -189,6 +202,16 @@ private static boolean isApplicable(ResolvedMethodDeclaration methodDeclaration, return !withWildcardTolerance || needForWildCardTolerance; } + private static boolean isArrayOfObject(ResolvedType type) { + return type.isArray() + && type.asArrayType().getComponentType().isReferenceType() + && type.asArrayType().getComponentType().asReferenceType().isJavaLangObject(); + } + + private static ResolvedArrayType convertToVariadicParameter(ResolvedType type) { + return type.isArray() ? type.asArrayType() : new ResolvedArrayType(type); + } + /* * Returns the last parameter index */ diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java index 15dcff5bf7..4150fd7f16 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/types/ResolvedArrayType.java @@ -107,10 +107,6 @@ public boolean isAssignableBy(ResolvedType other) { return false; } - private boolean isJavaLangObject(ResolvedType type) { - return type.isReferenceType() && type.asReferenceType().isJavaLangObject(); - } - @Override public ResolvedType replaceTypeVariables(ResolvedTypeParameterDeclaration tpToReplace, ResolvedType replaced, Map inferredTypes) { ResolvedType baseTypeReplaced = baseType.replaceTypeVariables(tpToReplace, replaced, inferredTypes); diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java index 1dd8da7801..09a79100a2 100755 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/types/ResolvedArrayTypeTest.java @@ -58,7 +58,7 @@ class ResolvedArrayTypeTest extends AbstractResolutionTest { @Test // An array of primitive type can be assigned another array of primitive type // if primitive type are the same. - void isAssignablePrimitiveType() { + void arrayOfPrimitiveIsAssignableByArrayOfSamePrimitiveType() { assertTrue(array(ResolvedPrimitiveType.DOUBLE).isAssignableBy(array(ResolvedPrimitiveType.DOUBLE))); assertTrue(array(ResolvedPrimitiveType.FLOAT).isAssignableBy(array(ResolvedPrimitiveType.FLOAT))); assertTrue(array(ResolvedPrimitiveType.LONG).isAssignableBy(array(ResolvedPrimitiveType.LONG))); @@ -69,7 +69,7 @@ void isAssignablePrimitiveType() { } @Test - void isNotAssignablePrimitiveType() { + void arrayOfPrimitiveIsNotAssignableByArrayOfDifferentPrimitiveType() { assertFalse(isAssignableBy(array(ResolvedPrimitiveType.DOUBLE), arrays(ResolvedPrimitiveType.FLOAT, ResolvedPrimitiveType.LONG, ResolvedPrimitiveType.INT, ResolvedPrimitiveType.BYTE, ResolvedPrimitiveType.SHORT, ResolvedPrimitiveType.CHAR))); @@ -94,7 +94,9 @@ void isNotAssignablePrimitiveType() { } @Test - void isNotAssignablePrimitiveTypeAndBoxedType() { + // An array of primitive type cannot be assigned to a Boxed type variable, + // because Boxed type is a class type other than Object + void arrayOfPrimitiveIsNotAssignableByArrayOfBoxedType() { assertFalse(array(ResolvedPrimitiveType.DOUBLE).isAssignableBy(array(rDouble))); assertFalse(array(ResolvedPrimitiveType.FLOAT).isAssignableBy(array(rFloat))); assertFalse(array(ResolvedPrimitiveType.LONG).isAssignableBy(array(rLong))); @@ -105,7 +107,7 @@ void isNotAssignablePrimitiveTypeAndBoxedType() { } @Test - void isAssignableWithNullType() { + void arrayOfPrimitiveIsAssignableByNullType() { assertTrue(array(ResolvedPrimitiveType.DOUBLE).isAssignableBy(NullType.INSTANCE)); assertTrue(array(ResolvedPrimitiveType.FLOAT).isAssignableBy(NullType.INSTANCE)); assertTrue(array(ResolvedPrimitiveType.LONG).isAssignableBy(NullType.INSTANCE)); @@ -118,7 +120,7 @@ void isAssignableWithNullType() { @Test // An array can be assigned only to a variable of a compatible array type, or to // a variable of type Object, Cloneable or java.io.Serializable. - void isAssignableWithObject() { + void objectIsAssignableByAnyArrayOfPrimitiveTypeOrReference() { assertTrue(rObject.isAssignableBy(array(ResolvedPrimitiveType.DOUBLE))); assertTrue(rObject.isAssignableBy(array(ResolvedPrimitiveType.FLOAT))); assertTrue(rObject.isAssignableBy(array(ResolvedPrimitiveType.LONG))); @@ -130,7 +132,7 @@ void isAssignableWithObject() { } @Test - void isAssignableWithCloneable() { + void cloneableIsAssignableByAnyArrayOfPrimitiveTypeOrReference() { assertTrue(rCloneable.isAssignableBy(array(ResolvedPrimitiveType.DOUBLE))); assertTrue(rCloneable.isAssignableBy(array(ResolvedPrimitiveType.FLOAT))); assertTrue(rCloneable.isAssignableBy(array(ResolvedPrimitiveType.LONG))); @@ -142,7 +144,7 @@ void isAssignableWithCloneable() { } @Test - void isAssignableWithSerializable() { + void serializableIsAssignableByAnyArrayOfPrimitiveTypeOrReference() { assertTrue(rSerializable.isAssignableBy(array(ResolvedPrimitiveType.DOUBLE))); assertTrue(rSerializable.isAssignableBy(array(ResolvedPrimitiveType.FLOAT))); assertTrue(rSerializable.isAssignableBy(array(ResolvedPrimitiveType.LONG))); @@ -154,27 +156,22 @@ void isAssignableWithSerializable() { } @Test - void isAssignableWithReference() { + void arrayOfSubTypeIsAssignableByArrayOfSuperType() { assertTrue(array(rCharSequence).isAssignableBy(array(rString))); } @Test - void isNotAssignableWithreference() { + void arrayOfReferenceIsNotAssignableByArrayOfOtherReference() { assertFalse(array(rString).isAssignableBy(array(rCharSequence))); - // An array of primitive type cannot be assigned to a Boxed type variable, - // because Boxed type is a class type other than Object - assertFalse(array(ResolvedPrimitiveType.LONG).isAssignableBy(rLong)); - assertTrue(array(rObject).isAssignableBy(array(rLong))); - assertFalse(array(rObject).isAssignableBy(array(ResolvedPrimitiveType.LONG))); } @Test - void ArrayOfObjectIsAssignableByArrayOfReference() { + void arrayOfObjectIsAssignableByArrayOfReference() { assertTrue(array(rObject).isAssignableBy(array(rLong))); } @Test - void ArrayOfObjectIsNotAssignableByArrayOfPrimitiveType() { + void arrayOfObjectIsNotAssignableByArrayOfPrimitiveType() { assertFalse(array(rObject).isAssignableBy(array(ResolvedPrimitiveType.LONG))); } From 1952dfe2d39035d1d527850734eeca55ebc20d6f Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Thu, 2 Mar 2023 21:17:04 +0400 Subject: [PATCH 05/32] Fix TextBlockLiteralExpr in LexicalDifferenceCalculator --- .../lexicalpreservation/Issue3936Test.java | 72 +++++++++++++++++++ .../LexicalDifferenceCalculator.java | 4 +- 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100755 javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java new file mode 100755 index 0000000000..e5d4da4e8d --- /dev/null +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser 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 Lesser General Public License for more details. + */ + +package com.github.javaparser.printer.lexicalpreservation; + +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; + +import com.github.javaparser.ast.body.VariableDeclarator; +import com.github.javaparser.ast.expr.TextBlockLiteralExpr; +import org.junit.jupiter.api.Test; + +public class Issue3936Test extends AbstractLexicalPreservingTest { + static final String given = "package eu.solven.cleanthat.engine.java.refactorer.cases.do_not_format_me;\n" + + "\n" + + "import java.util.Optional;\n" + + "\n" + + "public class SomeClass {\n" + + "\n" + + " String html = \"\" + \"\\n\"\n" + + " + \"\\t\\n\"\n" + + " + \"\\t\\t\\n\"\n" + + " + \"\\t\\n\"\n" + + " + \"\\t\\n\"\n" + + " + \"\\t\\t

Hello, world

\\n\"\n" + + " + \"\\t\\n\"\n" + + " + \"\\n\";\n" + + "}"; + + @Test + void test() { + considerCode(given); + + String newText = "firstRow\nsecondRow\nthirdRow"; + + LexicalPreservingPrinter.setup(cu); + + VariableDeclarator expr = cu.findFirst(VariableDeclarator.class).get(); + expr.setInitializer(new TextBlockLiteralExpr(newText)); + + String actual = LexicalPreservingPrinter.print(cu); + String expected ="package eu.solven.cleanthat.engine.java.refactorer.cases.do_not_format_me;\n" + + "\n" + + "import java.util.Optional;\n" + + "\n" + + "public class SomeClass {\n" + + "\n" + + " String html = \"\"\"\n" + + "firstRow\n" + + "secondRow\n" + + "thirdRow\"\"\";\n" + + "}"; + assertEqualsStringIgnoringEol(expected, actual); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index 7ee1c4753e..4c7119e655 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -290,9 +290,9 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List Date: Fri, 3 Mar 2023 12:21:41 +0400 Subject: [PATCH 06/32] Suggested fix: hardcoded specific LambdaExpr case in LexicalDifferenceCalculator --- .../lexicalpreservation/Issue3937Test.java | 72 +++++++++++++++++++ .../LexicalDifferenceCalculator.java | 8 ++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java new file mode 100644 index 0000000000..63da053869 --- /dev/null +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2007-2010 Júlio Vilmar Gesser. + * Copyright (C) 2011, 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser 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 Lesser General Public License for more details. + */ + +package com.github.javaparser.printer.lexicalpreservation; + +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.ast.expr.LambdaExpr; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; +import com.github.javaparser.ast.stmt.Statement; + +public class Issue3937Test extends AbstractLexicalPreservingTest { + static final String given = "package eu.solven.cleanthat.code_provider.inmemory;\n" + "\n" + + "import java.util.stream.Stream;\n" + + "\n" + + "class TestFileSystemCodeProvider {\n" + + " void testInMemoryFileSystem() {\n" + + "\n" + + " Stream.of(\"\").listFilesForContent(file -> {\n" + + " System.out.println(s);\n" + + " });\n" + + " }\n" + + "}\n" + + ""; + + @Test + void test() { + considerCode(given); + + LexicalPreservingPrinter.setup(cu); + + LambdaExpr lambdaExpr = cu.findFirst(LambdaExpr.class).get(); + Statement body = lambdaExpr.getBody(); + BlockStmt lambdaBLockStmt = (BlockStmt) body; + ExpressionStmt exprStmt = (ExpressionStmt) lambdaBLockStmt.getStatement(0); + lambdaExpr.setBody(new ExpressionStmt(exprStmt.getExpression())); + + String actual = LexicalPreservingPrinter.print(cu); + String expected = "package eu.solven.cleanthat.code_provider.inmemory;\n" + "\n" + + "import java.util.stream.Stream;\n" + + "\n" + + "class TestFileSystemCodeProvider {\n" + + " void testInMemoryFileSystem() {\n" + + "\n" + + " Stream.of(\"\").listFilesForContent(file -> System.out.println(s));\n" + + " }\n" + + "}\n" + + ""; + assertEqualsStringIgnoringEol(expected, actual); + } +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index 7ee1c4753e..3f583ae6d8 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -25,9 +25,12 @@ import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.expr.CharLiteralExpr; +import com.github.javaparser.ast.expr.LambdaExpr; import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.ast.expr.TextBlockLiteralExpr; import com.github.javaparser.ast.observer.ObservableProperty; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.printer.ConcreteSyntaxModel; import com.github.javaparser.printer.SourcePrinter; import com.github.javaparser.printer.Stringable; @@ -187,6 +190,9 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List Date: Fri, 3 Mar 2023 13:37:41 +0400 Subject: [PATCH 07/32] Leaner unitTest --- .../printer/lexicalpreservation/Issue3936Test.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java index e5d4da4e8d..6b51037089 100755 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3936Test.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; public class Issue3936Test extends AbstractLexicalPreservingTest { - static final String given = "package eu.solven.cleanthat.engine.java.refactorer.cases.do_not_format_me;\n" + static final String given = "package some.project;\n" + "\n" + "import java.util.Optional;\n" + "\n" @@ -48,7 +48,7 @@ public class Issue3936Test extends AbstractLexicalPreservingTest { void test() { considerCode(given); - String newText = "firstRow\nsecondRow\nthirdRow"; + String newText = "\tfirstRow\n\tsecondRow\n\tthirdRow"; LexicalPreservingPrinter.setup(cu); @@ -56,16 +56,16 @@ void test() { expr.setInitializer(new TextBlockLiteralExpr(newText)); String actual = LexicalPreservingPrinter.print(cu); - String expected ="package eu.solven.cleanthat.engine.java.refactorer.cases.do_not_format_me;\n" + String expected ="package some.project;\n" + "\n" + "import java.util.Optional;\n" + "\n" + "public class SomeClass {\n" + "\n" + " String html = \"\"\"\n" - + "firstRow\n" - + "secondRow\n" - + "thirdRow\"\"\";\n" + + "\tfirstRow\n" + + "\tsecondRow\n" + + "\tthirdRow\"\"\";\n" + "}"; assertEqualsStringIgnoringEol(expected, actual); } From f77f827a43ce006ec7c712bdeb880bfa2d3c9fe9 Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Fri, 3 Mar 2023 17:44:59 +0400 Subject: [PATCH 08/32] leaner unittest --- .../javaparser/printer/lexicalpreservation/Issue3937Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java index 63da053869..cc88b5d501 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java @@ -31,7 +31,7 @@ import com.github.javaparser.ast.stmt.Statement; public class Issue3937Test extends AbstractLexicalPreservingTest { - static final String given = "package eu.solven.cleanthat.code_provider.inmemory;\n" + "\n" + static final String given = "package custom.project;\n" + "\n" + "import java.util.stream.Stream;\n" + "\n" + "class TestFileSystemCodeProvider {\n" @@ -57,7 +57,7 @@ void test() { lambdaExpr.setBody(new ExpressionStmt(exprStmt.getExpression())); String actual = LexicalPreservingPrinter.print(cu); - String expected = "package eu.solven.cleanthat.code_provider.inmemory;\n" + "\n" + String expected = "package custom.project;\n" + "\n" + "import java.util.stream.Stream;\n" + "\n" + "class TestFileSystemCodeProvider {\n" From 14ce6cebd7c83bedae2126cb62bb2b001aaa3f7f Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Fri, 3 Mar 2023 17:51:13 +0400 Subject: [PATCH 09/32] Switch to proper EOL, as allowed by https://openjdk.java.net/jeps/378#1--Line-terminatorsx --- .../printer/concretesyntaxmodel/CsmTextBlock.java | 5 +++-- .../lexicalpreservation/LexicalDifferenceCalculator.java | 8 +++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmTextBlock.java b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmTextBlock.java index df43d20690..3fd7e4e7b9 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmTextBlock.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/concretesyntaxmodel/CsmTextBlock.java @@ -38,8 +38,9 @@ public ObservableProperty getProperty() { @Override public void prettyPrint(Node node, SourcePrinter printer) { - // Note that values within TextBlocks ALWAYS have the \n line ending, per https://openjdk.java.net/jeps/378#1--Line-terminators - printer.print("\"\"\"\n"); + printer.print("\"\"\""); + // Per https://openjdk.java.net/jeps/378#1--Line-terminators, any 'CRLF' and 'CR' are turned into 'LF' before interpreting the text + printer.println(); // TODO: Confirm if we need to force this to use {@code \n} separators printer.print(property.getValueAsStringAttribute(node)); printer.print("\"\"\""); diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index 4c7119e655..2f559c01bd 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -288,11 +288,13 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List Date: Fri, 3 Mar 2023 22:10:31 +0400 Subject: [PATCH 10/32] Simplify unitTest not to reuse the original Statement --- .../printer/lexicalpreservation/Issue3937Test.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java index cc88b5d501..51d62a3ced 100644 --- a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3937Test.java @@ -26,9 +26,9 @@ import org.junit.jupiter.api.Test; import com.github.javaparser.ast.expr.LambdaExpr; -import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.stmt.ExpressionStmt; -import com.github.javaparser.ast.stmt.Statement; public class Issue3937Test extends AbstractLexicalPreservingTest { static final String given = "package custom.project;\n" + "\n" @@ -51,19 +51,17 @@ void test() { LexicalPreservingPrinter.setup(cu); LambdaExpr lambdaExpr = cu.findFirst(LambdaExpr.class).get(); - Statement body = lambdaExpr.getBody(); - BlockStmt lambdaBLockStmt = (BlockStmt) body; - ExpressionStmt exprStmt = (ExpressionStmt) lambdaBLockStmt.getStatement(0); - lambdaExpr.setBody(new ExpressionStmt(exprStmt.getExpression())); + lambdaExpr.setBody(new ExpressionStmt(new MethodCallExpr(new NameExpr("SomeClass"), "someMethod"))); String actual = LexicalPreservingPrinter.print(cu); - String expected = "package custom.project;\n" + "\n" + String expected = "package custom.project;\n" + + "\n" + "import java.util.stream.Stream;\n" + "\n" + "class TestFileSystemCodeProvider {\n" + " void testInMemoryFileSystem() {\n" + "\n" - + " Stream.of(\"\").listFilesForContent(file -> System.out.println(s));\n" + + " Stream.of(\"\").listFilesForContent(file -> SomeClass.someMethod());\n" + " }\n" + "}\n" + ""; From 79fd273ffa2ece84bfe1b7af52b7f7b2cbaddec7 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Mon, 6 Mar 2023 14:51:02 +0100 Subject: [PATCH 11/32] Fix: issue on FunctionalInterfaceLogic but waiting for Return-Type-Substituable is fully implemented on reference type --- .../logic/FunctionalInterfaceLogic.java | 3 -- .../logic/FunctionalInterfaceLogicTest.java | 33 +++++++++++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java index 47c3c7572a..c0579982d2 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/FunctionalInterfaceLogic.java @@ -77,9 +77,6 @@ public static Optional getFunctionalMethod(ResolvedReferenceTypeDec } Iterator iterator = methods.iterator(); MethodUsage methodUsage = iterator.next(); - if (methods.size() == 1) { - return Optional.of(methodUsage); - } while (iterator.hasNext()) { MethodUsage otherMethodUsage = iterator.next(); if (!(methodUsage.isSameSignature(otherMethodUsage) diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java index 4bbef4f450..bf376bfdca 100755 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java @@ -217,10 +217,12 @@ void bazIsAFunctionalInterfaceBecauseMethodsItInheritsFromFooHaveTheSameSignatur assertFalse(methodUsage.isPresent()); } + /* + * Functional: signatures are logically "the same" + */ @Test - void withGenericMethods() { + void withGenericMethodsWithSameSignatures() { String code = "interface Action {};\n" - + "interface Exec { T execute(Action a); }\n" + "interface X { T execute(Action a); }\n" + "interface Y { S execute(Action a); }\n" + "interface Exec extends X, Y {}\n"; @@ -234,10 +236,12 @@ void withGenericMethods() { } + /* + * Error: different signatures, same erasure + */ @Test - void withGenericMethods2() { + void withGenericMethodsWithDifferentSignaturesAndSameErasure() { String code = "interface Action {};\n" - + "interface Exec { T execute(Action a); }\n" + "interface X { T execute(Action a); }\n" + "interface Y { S execute(Action a); }\n" + "interface Exec extends X, Y {}"; @@ -258,8 +262,7 @@ void withGenericMethods2() { * multiple methods that cannot be legally overridden with a single declaration. */ @Test - @Disabled("Return-Type-Substituable must be implemented on reference type.") - void genericFunctionalInterfaces() { + void genericFunctionalInterfacesWithReturnTypeSubstituable() { String code = "interface I { Object m(Class c); }\r\n" + "interface J { S m(Class c); }\r\n" + "interface K { T m(Class c); }\r\n" @@ -274,4 +277,22 @@ void genericFunctionalInterfaces() { } + @Test + @Disabled("Waiting Return-Type-Substituable is fully implemented on reference type.") + void genericFunctionalInterfacesWithGenericParameter() { + String code = + " public interface Foo extends java.util.function.Function {\n" + + " @Override\n" + + " T apply(String c);\n" + + " }\n"; + + CompilationUnit cu = StaticJavaParser.parse(code); + ClassOrInterfaceDeclaration classOrInterfaceDecl = Navigator.demandInterface(cu, "Foo"); + ResolvedInterfaceDeclaration resolvedDecl = new JavaParserInterfaceDeclaration(classOrInterfaceDecl, + typeSolver); + Optional methodUsage = FunctionalInterfaceLogic.getFunctionalMethod(resolvedDecl); + assertTrue(methodUsage.isPresent()); + + } + } From aebe3bb8e506c372e6323fc0813a5197283884be Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Mon, 6 Mar 2023 15:43:43 +0100 Subject: [PATCH 12/32] Fix: Init Return-Type-Substituable on reference type --- .../declarations/ResolvedMethodDeclaration.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java index d01e19f6fe..6c55d4b88a 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedMethodDeclaration.java @@ -81,10 +81,18 @@ default boolean isReturnTypeSubstituable(ResolvedType otherResolvedType) { // If R1 is a reference type then one of the following is true: // R1, adapted to the type parameters of d2 (§8.4.4), is a subtype of R2. + // Below we are trying to compare a reference type for example an Object to a type variable let's say T + // we can certainly simplify by saying that this is always true. + if (otherResolvedType.isTypeVariable()) { + return true; + } // R1 can be converted to a subtype of R2 by unchecked conversion (§5.1.9). // d1 does not have the same signature as d2 (§8.4.2), and R1 = |R2|. + if (returnType.describe().equals(otherResolvedType.erasure().describe())) { + return true; + } throw new UnsupportedOperationException("Return-Type-Substituable must be implemented on reference type."); } } From 7273d185e5bf298af1e526f4136c14f824f4955f Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 8 Mar 2023 20:52:25 +0400 Subject: [PATCH 13/32] Remove unused import --- .../printer/lexicalpreservation/LexicalDifferenceCalculator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index 3f583ae6d8..5004605ef9 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -29,7 +29,6 @@ import com.github.javaparser.ast.expr.StringLiteralExpr; import com.github.javaparser.ast.expr.TextBlockLiteralExpr; import com.github.javaparser.ast.observer.ObservableProperty; -import com.github.javaparser.ast.stmt.BlockStmt; import com.github.javaparser.ast.stmt.ExpressionStmt; import com.github.javaparser.printer.ConcreteSyntaxModel; import com.github.javaparser.printer.SourcePrinter; From 124a4870a611d518b96910abecd216fffb5d3edc Mon Sep 17 00:00:00 2001 From: Benoit Lacelle Date: Wed, 8 Mar 2023 20:56:33 +0400 Subject: [PATCH 14/32] Add comment, adjust indentation --- .../lexicalpreservation/LexicalDifferenceCalculator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index 5004605ef9..a070f5077e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -190,6 +190,7 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List Date: Wed, 8 Mar 2023 20:59:00 +0400 Subject: [PATCH 15/32] Fix indentation --- .../lexicalpreservation/LexicalDifferenceCalculator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java index a070f5077e..0651ad7cc6 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/LexicalDifferenceCalculator.java @@ -191,7 +191,7 @@ private void calculatedSyntaxModelForNode(CsmElement csm, Node node, List Date: Wed, 8 Mar 2023 22:22:51 +0100 Subject: [PATCH 16/32] Fix: Unit test since Return-Type-Substituable is fully implemented on reference type --- .../resolution/logic/FunctionalInterfaceLogicTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java index bf376bfdca..47319548db 100755 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/logic/FunctionalInterfaceLogicTest.java @@ -262,6 +262,7 @@ void withGenericMethodsWithDifferentSignaturesAndSameErasure() { * multiple methods that cannot be legally overridden with a single declaration. */ @Test + @Disabled("Waiting Return-Type-Substituable is fully implemented on reference type.") void genericFunctionalInterfacesWithReturnTypeSubstituable() { String code = "interface I { Object m(Class c); }\r\n" + "interface J { S m(Class c); }\r\n" From 2195a4229d6c4684f74ad3e9ac1f314a8d27fd1c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Mar 2023 16:35:30 +0000 Subject: [PATCH 17/32] chore(deps): update dependency com.puppycrawl.tools:checkstyle to v10.8.1 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e5cdfae1f0..7bff0939f3 100644 --- a/pom.xml +++ b/pom.xml @@ -352,7 +352,7 @@ com.puppycrawl.tools checkstyle - 10.8.0 + 10.8.1 From 6266e45a108e27ee2bba009bad55ebc9d7c7ebbf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 23:56:56 +0000 Subject: [PATCH 18/32] chore(deps): bump actions/checkout from 3.3.0 to 3.4.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.3.0...v3.4.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/create_github_release.yml | 2 +- .github/workflows/maven_tests.yml | 4 ++-- .github/workflows/prepare_release_changelog.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create_github_release.yml b/.github/workflows/create_github_release.yml index 495f70a220..3ae9aacea5 100644 --- a/.github/workflows/create_github_release.yml +++ b/.github/workflows/create_github_release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.4.0 - name: Create Release id: create_release diff --git a/.github/workflows/maven_tests.yml b/.github/workflows/maven_tests.yml index 32b7efed55..d5f64403f8 100644 --- a/.github/workflows/maven_tests.yml +++ b/.github/workflows/maven_tests.yml @@ -45,7 +45,7 @@ jobs: steps: ## Checkout the current version of the code from the repo. - name: Checkout latest code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.4.0 with: fetch-depth: "0" @@ -109,7 +109,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout latest code - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.4.0 with: fetch-depth: "0" - name: Set up JDK 11 diff --git a/.github/workflows/prepare_release_changelog.yml b/.github/workflows/prepare_release_changelog.yml index 0f91eea3df..2cd862313a 100644 --- a/.github/workflows/prepare_release_changelog.yml +++ b/.github/workflows/prepare_release_changelog.yml @@ -15,7 +15,7 @@ jobs: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.4.0 # Setup Java 11 environment for the next steps - name: Setup Java From 03a28e96e8c6655ce6829e8b5c794de5f5815b79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Mar 2023 23:56:51 +0000 Subject: [PATCH 19/32] chore(deps): bump checkstyle from 10.8.1 to 10.9.1 Bumps [checkstyle](https://github.com/checkstyle/checkstyle) from 10.8.1 to 10.9.1. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.8.1...checkstyle-10.9.1) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7bff0939f3..33540394b3 100644 --- a/pom.xml +++ b/pom.xml @@ -352,7 +352,7 @@ com.puppycrawl.tools checkstyle - 10.8.1 + 10.9.1 From a60a846a6ca59fd1421625c47261f0797897ce3a Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Fri, 17 Mar 2023 08:24:10 +0100 Subject: [PATCH 20/32] Fix: issue 3949 LexicalPreservingPrinter Ignores Changes to LambdaExpr Body --- .../lexicalpreservation/Issue3949Test.java | 48 +++++++++++++++ .../ast/observer/ObservableProperty.java | 19 ++---- .../lexicalpreservation/changes/Change.java | 60 ++++++++++++++++++- .../changes/ListAdditionChange.java | 9 ++- .../changes/ListRemovalChange.java | 9 ++- .../changes/ListReplacementChange.java | 9 ++- .../lexicalpreservation/changes/NoChange.java | 5 ++ .../changes/PropertyChange.java | 6 +- 8 files changed, 142 insertions(+), 23 deletions(-) create mode 100755 javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3949Test.java diff --git a/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3949Test.java b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3949Test.java new file mode 100755 index 0000000000..05977b1b09 --- /dev/null +++ b/javaparser-core-testing/src/test/java/com/github/javaparser/printer/lexicalpreservation/Issue3949Test.java @@ -0,0 +1,48 @@ +package com.github.javaparser.printer.lexicalpreservation; + +import static com.github.javaparser.utils.TestUtils.assertEqualsStringIgnoringEol; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.ast.expr.LambdaExpr; +import com.github.javaparser.ast.stmt.BlockStmt; +import com.github.javaparser.ast.stmt.BreakStmt; +import com.github.javaparser.ast.stmt.ExpressionStmt; + +class Issue3949Test extends AbstractLexicalPreservingTest { + + @Test + public void test() { + considerCode( + "class A {\n" + + "\n" + + " void foo() {\n" + + " Consumer lambda = a -> System.out.println(a);\n" + + " }\n" + + "}"); + + ExpressionStmt estmt = cu.findAll(ExpressionStmt.class).get(1).clone(); + LambdaExpr lexpr = cu.findAll(LambdaExpr.class).get(0); + LexicalPreservingPrinter.setup(cu); + + BlockStmt block = new BlockStmt(); + BreakStmt bstmt = new BreakStmt(); + block.addStatement(new ExpressionStmt(estmt.getExpression())); + block.addStatement(bstmt); + lexpr.setBody(block); + + String expected = + "class A {\n" + + "\n" + + " void foo() {\n" + + " Consumer lambda = a -> {\n" + + " System.out.println(a);\n" + + " break;\n" + + " };\n" + + " }\n" + + "}"; + + assertEqualsStringIgnoringEol(expected, LexicalPreservingPrinter.print(cu)); + } + +} diff --git a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java index 6ff2deace4..9382c6554a 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java +++ b/javaparser-core/src/main/java/com/github/javaparser/ast/observer/ObservableProperty.java @@ -20,16 +20,16 @@ */ package com.github.javaparser.ast.observer; -import com.github.javaparser.ast.Generated; -import com.github.javaparser.ast.Node; -import com.github.javaparser.ast.NodeList; -import com.github.javaparser.utils.Utils; - import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Collection; import java.util.Optional; +import com.github.javaparser.ast.Generated; +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.NodeList; +import com.github.javaparser.utils.Utils; + /** * Properties considered by the AstObserver */ @@ -287,14 +287,7 @@ public boolean isNull(Node node) { } public boolean isNullOrNotPresent(Node node) { - Object result = getRawValue(node); - if (result == null) { - return true; - } - if (result instanceof Optional) { - return !((Optional) result).isPresent(); - } - return false; + return Utils.valueIsNullOrEmptyStringOrOptional(getRawValue(node)); } public boolean isNullOrEmpty(Node node) { diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java index 826c0a8365..bbc71ef437 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java @@ -39,11 +39,69 @@ default boolean evaluate(CsmConditional csmConditional, Node node) { case IS_EMPTY: return Utils.valueIsNullOrEmpty(getValue(csmConditional.getProperty(), node)); case IS_PRESENT: - return !Utils.valueIsNullOrEmptyStringOrOptional(getValue(csmConditional.getProperty(), node)); + return !Utils.valueIsNullOrEmptyStringOrOptional(getValue(csmConditional.getProperty(), node)) + && !isEvaluatedOnDerivedProperty(csmConditional.getProperty()); default: throw new UnsupportedOperationException("" + csmConditional.getProperty() + " " + csmConditional.getCondition()); } } + /* + * Evaluate on derived property. + * + * Currently the evaluation of the conditions is carried out in relation to the + * presence of value in the attributes of a class but this is not quite correct. + * + * Indeed, there are attributes that are derived. The meaning of a derived + * attribute (annotated with the DerivedProperty annotation) is not very clear. + * + * Assuming that it is an existing attribute and accessible by another property, + * for example this is the case for the EXPRESSION_BODY property which allows + * access to a derived field (which is also accessible by the BODY property). + * + * The 2 properties EXPRESSION_BODY and BODY have a different meaning because + * one references a simple expression while the other references a list of + * expressions (this distinction is particularly interesting in the case of + * lambda expressions). + * + * In this particular case, the verification of the condition must not succeed + * if the nature of the property is modified. So if we modify a lamba expression + * composed of a single expression by replacing it with a list of expressions, + * the evaluation of a condition relating to the presence of the EXPRESSION_BODY + * property, which makes it possible to determine the nature of the change, + * cannot not lead to a verified proposition which could be the case if we only + * consider that the field referenced by the EXPRESSION_BODY property has an + * acceptable value before the actual modification. + * + * This is why we also check if it is a derived property whose name coincides + * with the updated property. If this is the case, we admit that the + * verification of the condition must fail so that we can execute the else + * clause of the condition. I'm not sure this issue #3949 is completely resolved by + * this change. + */ + default boolean isEvaluatedOnDerivedProperty(ObservableProperty property) { + ObservableProperty currentProperty = getProperty(); + /* + * Assuming that by convention the derived property is suffixed with the name of + * the property it derives from (e.g. EXPRESSION_BODY which matches an + * expression would derive from BODY which matches a list of expressions), we + * could deduce that EXPRESSION_BODY and BODY actually represent the same + * field but the validation condition must not be checked. + * Be careful because NoChange property must not affect this evaluation. + */ + return currentProperty != null + && (property.isDerived() + && property.name().endsWith(currentProperty.name())); + } + + /* + * Assuming that by convention the derived property is suffixed + * with the name of the property it derives from (e.g. EXPRESSION_BODY which + * matches an expression vs a list of expressions would derive from BODY) We + * could deduce that EXPRESSION_BODY and BODY actually represent the same + * property but the validation condition is not checked. + */ + ObservableProperty getProperty(); + Object getValue(ObservableProperty property, Node node); } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java index 88b04951fe..029cd0de84 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListAdditionChange.java @@ -20,12 +20,12 @@ */ package com.github.javaparser.printer.lexicalpreservation.changes; +import java.util.Optional; + import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.observer.ObservableProperty; -import java.util.Optional; - /** * The Addition of an element to a list. */ @@ -66,4 +66,9 @@ public Object getValue(ObservableProperty property, Node node) { return new NoChange().getValue(property, node); } } + + @Override + public ObservableProperty getProperty() { + return observableProperty; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java index 2616f8c080..888770b62e 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListRemovalChange.java @@ -20,12 +20,12 @@ */ package com.github.javaparser.printer.lexicalpreservation.changes; +import java.util.Optional; + import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.observer.ObservableProperty; -import java.util.Optional; - /** * The removal of an element from a list. */ @@ -64,4 +64,9 @@ public Object getValue(ObservableProperty property, Node node) { return new NoChange().getValue(property, node); } } + + @Override + public ObservableProperty getProperty() { + return observableProperty; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java index 50b7b6a765..a63a7b5124 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/ListReplacementChange.java @@ -20,12 +20,12 @@ */ package com.github.javaparser.printer.lexicalpreservation.changes; +import java.util.Optional; + import com.github.javaparser.ast.Node; import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.observer.ObservableProperty; -import java.util.Optional; - /** * The replacement of an element in a list. */ @@ -66,4 +66,9 @@ public Object getValue(ObservableProperty property, Node node) { return new NoChange().getValue(property, node); } } + + @Override + public ObservableProperty getProperty() { + return observableProperty; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/NoChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/NoChange.java index 50ca881172..f8774fd7f3 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/NoChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/NoChange.java @@ -32,4 +32,9 @@ public class NoChange implements Change { public Object getValue(ObservableProperty property, Node node) { return property.getRawValue(node); } + + @Override + public ObservableProperty getProperty() { + return null; + } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/PropertyChange.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/PropertyChange.java index 86c3966e3e..57998eafbd 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/PropertyChange.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/PropertyChange.java @@ -40,7 +40,8 @@ public PropertyChange(ObservableProperty property, Object oldValue, Object newVa this.newValue = newValue; } - public ObservableProperty getProperty() { + @Override + public ObservableProperty getProperty() { return property; } @@ -56,8 +57,7 @@ public Object getNewValue() { public Object getValue(ObservableProperty property, Node node) { if (property == this.property) { return newValue; - } else { - return property.getRawValue(node); } + return property.getRawValue(node); } } From e82fde337bcb81d3e44eaa5e2a6a9aec0ec89056 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Fri, 17 Mar 2023 08:42:59 +0100 Subject: [PATCH 21/32] Improve explanation on LPP behavior --- .../lexicalpreservation/changes/Change.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java index bbc71ef437..bd89503a9d 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java +++ b/javaparser-core/src/main/java/com/github/javaparser/printer/lexicalpreservation/changes/Change.java @@ -50,11 +50,12 @@ default boolean evaluate(CsmConditional csmConditional, Node node) { * Evaluate on derived property. * * Currently the evaluation of the conditions is carried out in relation to the - * presence of value in the attributes of a class but this is not quite correct. + * presence of value in the field/attribute of a class referenced by a property + * (for example the BODY property is referenced to the body field in the + * LambdaExpr class) but this is not quite correct. * * Indeed, there are attributes that are derived. The meaning of a derived * attribute (annotated with the DerivedProperty annotation) is not very clear. - * * Assuming that it is an existing attribute and accessible by another property, * for example this is the case for the EXPRESSION_BODY property which allows * access to a derived field (which is also accessible by the BODY property). @@ -64,27 +65,34 @@ default boolean evaluate(CsmConditional csmConditional, Node node) { * expressions (this distinction is particularly interesting in the case of * lambda expressions). * - * In this particular case, the verification of the condition must not succeed - * if the nature of the property is modified. So if we modify a lamba expression - * composed of a single expression by replacing it with a list of expressions, - * the evaluation of a condition relating to the presence of the EXPRESSION_BODY - * property, which makes it possible to determine the nature of the change, - * cannot not lead to a verified proposition which could be the case if we only - * consider that the field referenced by the EXPRESSION_BODY property has an - * acceptable value before the actual modification. + * In this particular case, the verification of the condition defined in the + * syntax model used by LPP must not succeed if the nature of the property is + * modified. So if we modify a lamba expression composed of a single expression + * by replacing it with a list of expressions, the evaluation of a condition + * relating to the presence of the EXPRESSION_BODY property, which makes it + * possible to determine the nature of the change, cannot not lead to a verified + * proposition which could be the case if we only consider that the field + * referenced by the EXPRESSION_BODY property has an acceptable value before the + * actual modification. * * This is why we also check if it is a derived property whose name coincides - * with the updated property. If this is the case, we admit that the + * (*) with the updated property. If this is the case, we admit that the * verification of the condition must fail so that we can execute the else - * clause of the condition. I'm not sure this issue #3949 is completely resolved by - * this change. + * clause of the condition. I'm not sure this issue #3949 is completely resolved + * by this change. + * + * (*) Assuming that by convention the derived property is suffixed with the + * name of the property it derives from (e.g.. EXPRESSION_BODY which matches an + * expression would derive from BODY which matches a list of expressions), we + * could deduce that EXPRESSION_BODY and BODY actually represent the same field + * but the validation condition must not be checked. */ default boolean isEvaluatedOnDerivedProperty(ObservableProperty property) { ObservableProperty currentProperty = getProperty(); /* - * Assuming that by convention the derived property is suffixed with the name of + * By convention we admit that the derived property is suffixed with the name of * the property it derives from (e.g. EXPRESSION_BODY which matches an - * expression would derive from BODY which matches a list of expressions), we + * expression would derive from BODY which matches a list of expressions), so we * could deduce that EXPRESSION_BODY and BODY actually represent the same * field but the validation condition must not be checked. * Be careful because NoChange property must not affect this evaluation. From 6501010db205f674795f05edb00278975b5684fa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:57:59 +0000 Subject: [PATCH 22/32] chore(deps): update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.0.0 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7bff0939f3..47574dc130 100644 --- a/pom.xml +++ b/pom.xml @@ -304,7 +304,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M9 + 3.0.0 org.codehaus.mojo From 6b0524897ba81fbf3b312047a6043671eb7f4af2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Mar 2023 23:56:44 +0000 Subject: [PATCH 23/32] chore(deps): bump maven-scm-plugin from 1.13.0 to 2.0.0 Bumps [maven-scm-plugin](https://github.com/apache/maven-scm) from 1.13.0 to 2.0.0. - [Release notes](https://github.com/apache/maven-scm/releases) - [Commits](https://github.com/apache/maven-scm/compare/maven-scm-1.13.0...maven-scm-2.0.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-scm-plugin dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4406238314..5dfa4a0757 100644 --- a/pom.xml +++ b/pom.xml @@ -248,7 +248,7 @@ org.apache.maven.plugins maven-scm-plugin - 1.13.0 + 2.0.0 org.apache.maven.plugins From f29c4b43a930453af3b238543a2ac5542d2889d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 Mar 2023 11:08:15 +0000 Subject: [PATCH 24/32] chore(deps): update dependency maven-wrapper to v3.2.0 --- .mvn/wrapper/maven-wrapper.jar | Bin 59925 -> 62547 bytes .mvn/wrapper/maven-wrapper.properties | 4 +- mvnw | 218 +++++++++++++------------- mvnw.cmd | 31 +++- 4 files changed, 131 insertions(+), 122 deletions(-) diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index bf82ff01c6cdae4a1bb754a6e062954d77ac5c11..cb28b0e37c7d206feb564310fdeec0927af4123a 100644 GIT binary patch delta 52729 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%0DIoqqGCqH%97HM??=#psgoIz5zcKJ ziL*ga$GY5g;VhDGxQ*^%p<1sp|<$VBw9P)P#xsb%s4cw?b-$t4|iBB5%x^1n(HwDpd}!Fcy&SlN0VVXvtV+t6GG z!nm6O=Nf0Rzt?~#>G@Bo);(D9DMn(PnHATmqBr=#ESZ~{DwFgkwWtBA9AChXyLzE&HFCl7M9zwS<=?fG z*!sN=ZRXxsBXFVz(j2xl*w@D#N-W(G2PFl!KVvc@hgXOw)SY}G4#zLMJa&M`UOz3D zw3hm_OYIj!uy6YPO+poT7cr|iA*&;z_XF}RXfnjMaQkJl$B%i;HprS|R6UpbMaL{zwnfbAVP z!T7Ak7`cD&BORlK^G-F3XVU@S^5y=1OZ>VoX9R~Zw~0yi*y*+8cW`b8CegBPh0TnP z>};YsLoL61jp9qNtZm+D)Jx~mg;Vdax&-t%2TSUSLv^nH@_EbEg*CZo9cpbC=vf_UA)6 za6VzTW*9qOv$52Sy^+TR+fz?)tNz*!gjZ(VPrvBMj z1$tr~2(DBzFQ&%<<+*_IO4F%-4U<6y4w^suufE2z4y zPU>Tmk9TdwFO=Mb1vR3%q~~)RH!O^k6X8|2+eDL6XIYY%c9wdP9J86CFnE|oKH(Q_@ ziz-uN*KcA@&kh(KA6=cC&y~M@8~fC+@3w*rZf=h}_2Ge|dox??2WdQwJ@N4u(|2zp zgqwVSX(QrH-2m9~+eqoO;kJvnoMKkPn&9Z@2TGm>^tCMxDWOAtWUGhd^*<@KfLOw* zAwM%wHEU%4SwREUQABKe(G0-3@O0#Djbs7@pzHDvS-%Q;XpH+*eWloa2i2CTh(vn+z z#yXlhbqv)PA$5DC9>4dcnS-Yv?a~JFNNF$EusNp@EQdf;%ud9e?#%jv%pJieuTRbH zBed?UjGam7av@rDr5UY`t6y1zt>?SN@I6*-p0q2qh2blCU@P3%!6!LdSye4%t|OGC z?qO8=2`e?qTDx93#(GLt5p5Oa>&M}S-TkQKS(=v?$cM7$yY!hr`iGS{ZwJ2}e}v|; zP04Et#{}R`WQ@{rxecCAq_{ru{ox=xD$)vS828dkj{ZTD$~&U9V==^ON7%FNOE#Ds zOg7aQ!@(^Q$aQqE3Xy6)W}szf1ea1kg|rK|9!v$^lJxqIrEb5^yF*-oriz5~0y6>X zr%~T(#)2@fLo)BGve)JS0oezSC4P}GM=aU+_$(mULsPNpzk{}`qtMfp(I&3$_V=b2 zl827qmaTE2&T2m^61uRmCy`P0Ny^wCN0q*mc;ufv&pCp)F#cyX2@G6P_fC2$a2{p4 zrE+Dr2417&3Q7EM6O&zyqmv4Pp>d^wN}$u9eP918397C}g#Yo~x1f?3XeR*#$bWM^ zcw=3hlL*5gQGWhJ>u69!Q~)GOC?F?J{Mu%69IT9`zQK>|GM!NDr?qQZquJ)m!6G2 zP=+x@sX%XZ$u=u{7Xplj)jD-4lN7-jbr!xFb&;vuJx$&QE=4z3t*eO+j_bPB`&*At zsz`?%E?_)@b%Y)~5;SlYy ztk+8}sxZ-lK?SN-%~v4M^8ir%>x3h`bBkywSqClCI;<^Sw-S8Swz zIx+8bjI<)%_!LqoM1hI@rjWE1Nx+G3>$~Ev7tp0kKxrryx_w$!9RwkNJ|opb(*8x9 zLry54eyvk=B}sELSPPVWn6hLC^9OoT9Q4@D<@QJsUg8h2|8Ff;Tq6i_=v!!nf&1}8 z@;`%a-W+Lw)oR-6II5_h@aYTyOz3d9uth1Gz95l+&2?n0;<)ui`?*B|n<4lyMDT=k z4(7f62e&r09iOGt#k2V(v#(f$j;>2)EL%zRUo4td)0|$@Yi}Dn-IFg5*Z9Dn3^BE& zO})fIaeJcF1F{2?BS{GfTM9;^CfZ9z+$Bm><)$=1?O8)+s}vh5O|NB&@9Zme-q~e& zwpDdOO*UlNLU!e112#v2gSdZWwz=Gzx;~)b*vMjI@xJR9)FqKI7H(TF!$wjw=>kD~ zb-9{R=Vw<(kC|P)u~o>lJtL~z5_YW9xh~WDrnB8vKIf8JQ$R-I4KiH>9 zW-I|vOG#!Tzt5hLL@4%*F-Upptg?V;_K&-$NN$w0`va`~V|pArs@3phYGj42Hf&+O z6G7ZfMwGAIMlpDkrlzt}$?vmsrkZ{10Wc=7zi0zGCqM$>L4u);IpvmSp^F?tn@MU? zD9{@TNFxc6pb=V6Y(=>`M{!t&O@8iPE?Nj+6dW;`p~$c{rU@p0EOH3jK35^?I8`uh zUG7ZG2IW-4!KF$!3K5x!&IlaQ`?D2zuGmukDtNK+Q~iRZx*T?iK$6@<8yMAwzy~^b z{C->B)w-N2|6lU$c*a0(*nq3BSoQV&^^%O{1HMVdI&EZ;&E#9Ut9T;WnexuabJ#wh zm8KrGYxghu==Vl3vmiwk+Vc1wX7W#;<`1^LbNcC1O&J_-@Bwv9flbUt&5 zMwggPH5T+_RXp*pZ0{$b_O_A?grsI5h$ILlaV08KMEPwqHR=UiG%}3?Q`C_sBbFWU z%yP5$8p)DT>9g7j&%qw-!%V`4g!r`QD~R=(DHIY{|K>9(_CRakvFy zIE^HUUAdRs5}B)XiKV6-CB&J$BC-lU>T-GAxs#tD6|P7?Xa^faM{KBPZ4*B5D%^={ zHNGYJ0zKRQK_YysN^6MT@VY5-0O{gwry%eSR{qNfj^%XF!zh!Jyh}L)DR50^inXHY z)aj-FPyD>t+GK?rE8dWVlMC;p3zT{oD}~6_V0LGCz?~M@)-V zyZPsxl#)u_*5GZ<`olj*eJ;?-8GxPll^2-TQ&An!n|@d?*y1@W`2-d%2h$b3Fj^fu zKZ^9`+uu9R+;yuPt-eRB_o9=XIh{kBpcqMRr88p(FWYMwbWls6(w7OGVH~a#7?2II zi_06^fTbspgZd+6&=N3M#D3xf4NOWIJ9eK5JhYn=rzAOB+#Lq9n z$<-(5mfo$AH!<=9%mkAdvk+z!mRFs@e5AxYikW>M{@=8Z|2ym>kgLF0 zA@R*k1}HBLB8WMhE4d}xNFyCcF{^FCl1c}FBn0c5CmecfgFhdFZL6?Zw@7s>5TbwZbXHQXt#BSE*2R{ z3glc%BHkIwvUIw&CYOTn&-B`C9vfV##H<#uP$L|cj4G=>e#Rv|nl_+P!6Qj@GTR=z zjxyD`L<7}9R9Ami5A&By3@+hI^uKw(31gEgZ~EU(0TGh?MSWqF{(>kf*|R2}ag=~} z6NX$F5t&(s&#ii40|=g&^wfuE7x{pIiFpljE2~-=g|pCd$CqpdP}Z+A7r+nm{;p~x zO&o%w!h6kSJ@q#-+vatrxKx^+>Y3nI4Qlzi!s=I{U}#t7h+tk7)`7YR>1AF=Pf*uN zAHL8Jl;v5`DcEI=(QboBWYa32-^Rqt4QH?9|6S#?wo3jbnONx|3{={Z8el->OW!y< z+Ib&gKcQoZfbNL#mjTPqn{9Zj;$Dtoqt#URVWa=Hok&e8r44{>c_#k#{_vG^)x3Ntn% z()`FLVqlaX8Y&R64rucP;j4hU96M{#(ZdPv|GK5^XEBVz*pMf->p924&h&ePqJc73 zVCo>>U`>O_-$*&=QD$m_1S5aJA)~w2u_-G47zHPjLw8li1I@R!<;|>AUM9w#VWD>I z#nA)HW=A`tbyrn~mX_yFLPkce8Q$43_m{Y-m;kj@>6)_Bipit)T|U=v`&~jk>`jjN z_~j_e5jl!l@(+KsG;cK42edLFC>j^4%2%qzrJ7$>*qZDFIM{0}1lrgZm~l427riyx z7|Fb=E9ZUe|NVxOVkD1MzsaNzF#kg)Rg9)i^zwoQCaXz0p@^e?t|#y|u;?j7tp-9# zHyIeC3)e;Ujncq3z{S_shf9hn5yxUpQ4}IcC-C=^wgySVOH#3kmPr*m?#A)QSG-55 zQ2l)KXF?AslDu1j7*9APOL>aIT z7zF-pD8|5im#%EBMXHrKAhIz}mXcCfFEp$L)+w=eYS20?XnLw05nhb^1cOlh-Twx= z7qXW%U_)zWAL2*X5@W(FQox8%%tG+A2r($mm{_qC@;BDvMahrFd~AxSRdXrqy(FMp9M4r^B%Kuk(;M69 z(3W@Ltlnp;QJ@b8N5mU0xTG_*A%eP2xvhw3@`J~4Upw-U6{t0Dk+kd|U`1PT2;{-s zq~XG`Z8;ts%Ci4p9OyIe=nVY9l$8Aj1p(E@=(ekD3zVmj>`1RY8g14r zs%-v|QdWJ%9(3Nn*ARiWS@`Hsm65oNJYkRZ+UPmAm{lP=<=WJKSi1gDI%ZhZJW#qX z)HRYhl?^U8lu|x2ujU`=U%;tdmg2anSHbGWVRXo9q}k}=kkZd59aFHgHfsS79AUm@ z8=!?fmofLt*qZw#m71OA2IWg|ZvG;Er=^)e_SsrJDpEI^J(LY$s=mMzNglH2URebb zjRFd9k;|yF8LsUnEA6Htal zB5xgXP?|`$WR(nklb9h7gE%w5&kp+>#D|7H-qgO~xH;{^2J>t)rEx7)?wQ*2g6a4c z2|1_`4xz*~Vf}i(pdkzh*h=TKKJ1UVNPYgDQhv|m&5t0R1;^t05*I&buUpFOmD77} z@0$fr&QD~TPweqC>3cgu%rB?`?JyEO0RF)Hm^#Pg&2I>Er>s5pLG*nfKQYH6bU0pB zm;2jF?618M&{v<_?ihh6xzMm9fC%CU2eQPR6JIo=w^(c8U*{~4*Q~IYASd(DpI5es z9z+^>f26Er`z@a09y{mmQVdQ}@RaKG34g!K@;8r07B&6U9ZoJvWVlA-0otSCwVk5$ zJEV%j^{Btr_**AjAi=%@(Fl$uiJU=h?V}Qq>~?=`8DM?RIxf1zF zF@e!Ai7K1ce9V~*E)7itwS{UEp0>by^Y&LZygY3eA-1#gAw*7ZXZnvC| zEoY{>$u^s4Dn4{el9nL5;H1Z7tV_RL-f1nXVdV^Rv@GMH9dJ_1dd%XBGfB_xI#p)T zEbCO|&2>W1^AxD;jg{y41HTMv17L{bk>ckpk0)hYOl-56p7NxRN{o;24$^*glD!$E z6~xTi`@jr+f%xtKpB@OT4ktavIcbpaJBlx{x`+sJ7YWTs|Hk>j=6=?|>R@kiDj;wegQTy<) z#lDrwRGQM&ZJbgsPNsb$`1HykA~Z(J)xc^AUVm3BKnUua#{H9$I}f>cXTs4<4_O#2 zvost$k8Z_zp_@}6kJ&Jhu z$`F~F)Z|+)U-_D?)(by`;2mC0xW0=QHV3pP5YO?Q*PSca=8*Zj%)1~y++n{Yx zUR2)Zin}Yb5uiaTePgEu6j7?m`WTrd)pnc(8Z5Y5quQPob=`Cq$xSAiz{q~ebUBij zQPynA3Ci}h=);OMdxOaaTDL5N`{F-XGVib6FSAn7Y6V|=g3|i7vrb6_7+ldBVb&p-{rxQOGI)Ow)4IcD!TjgdD(y zJU@D-(2jj|m#;c1iVa5uP!4Q_#d(h-|AU({pVX`)DAEV5x~tB~)AXg@qOCK;QWIM4 zyC4M;8;}@e5j)CPw{p>+qFb*JSlxBIfIYoSlRx!b^0;ADOOKDn%Rz6&FXXP7>AUPg z!+qTTn|E8eh>UusV?gH}n$EL!^(CZ?>V%jigX$AngUS;rSz{OyC>>pQA7*toMsi+t2T7?iaLVA@^)1;HYk_2u zzOgK~O{fWazs`sQ4V{X2y^vFL0WVmDQSPn%!qnQU_OMRl3E{5G*;onoC{3ChY}qP$ zNm68~3-QBtVbjA-$+HiQ^?3#%4D0Xwg9CrLt?s;c^aOX?aNN}8I$KgHMiI$An-bb3 z&fUZAoEM)R#Pj34QEw}PIo~@#1&_C2ueH-G=T@yK=2m-wZ0mYA+anphgp`GvP4mCk z&G7~%&yBHiMx@_IHMFr zT3XN)?KI=88wEvtn6G3$j?PZ8k1)Z)_SuZCL*g=fr@He&8q4cUj-82>{ z@4}`xB2aH-P#pe7?>XR5mb9)_$L{#Kall2N7VV74M-!CHMq89L`l30_8&mXx(uT3* zo||~49>U0Ae4MHO_wTstCL7iRl2{Wg4J=Oi&kVVcokrTN2HK`Pf_*qNG%XWtM0%Cz z2q_t=ggn*){NL-%G)5Wb~9>fl3MMPP`;RhkXHplCf9A=cuZ#;C=QHd@9nT~=M z7_#;tu5|}Iy3aCNmIwx~(o#;hiDjZtzo7ngQUBBdG!+rX$f0GZBoN31tIS&;>F!|% zjR`N?xy>{N$i;}NBX3C{As=Q_2I;I`mYonz1})yqYt>)CRbox|`mz)`$b=kn?A=K? zXjZ}eA*-t3yXGoUr42&EU}O6Uq|EoZ+a7y72#WA0ku!{AK$oM-msX*QW!Du?60wOM z@p&6GXc7sN+d%WpPS9(#dJrA(AVjyaKBZkZQKW_%Niy2ObV-$&Uh4$7p~}2~5b9#! zqr<_+9I!=0oM;n>1SuyQuIv3nx3R)7wCFLi4Gme^PSNUeo_t)9SzWFI+I*-owC<3_ zByj#Bc2<4PwI-&>}{@nTqCP4{sUCJvk01D4q+Turv zPvMo?UTXgZE#`eM44la*GVRHyZxl{er!&WL(1Ma!(lV}=l$+qtk9qA9|Cf;x!L(*G zyNnlH3j%FKD+h~3Z{3hOq$)qhI^zV()rxhU<%l^#kgE@mq8Qx+`J5Va7o2#2h_FxA z+FH1d|KA_?84c1F!M6Yz{w+XC{U_GQ?BjgL8k=tc6494z&Gpn&S{YVDg+`Pj?iaG2 z7R*m6cV%m6b1jy|)=U$ed9u!|DWzBO_uZZ{ab6Y9ZtuI_U!nZMu}*Fa$WjqBOHS_% zUe}xL%x*azSJ^KgwfI1AhL|^OA;?Mv=d3=>{(#FQB|~jYZPN-WymU3o6{L-gl0+aA z)!|~7ZZ)(OvwF)U>)xVFsoQjy9ruyaT6z0RwxLh9y=#Sa@)lMAV;qbrqf=LRY13LA zHFKM9jIjBf13WgjYwLLPHVYx{VlB8Xh(k^tCSu@{O{=x`n(p2rsfT)7Nd!#LWVy_t zZmD%LOVfUVj5JO@L!1`@Ubu>=Mlmp{C(D8e>cl3fZvj!bGXfsB_5c~ckp>k&20Ku- zH^-r>LEeT*OX^$}p4e`FKVZ3$Z15HsApq_Ng*nt+ z;+Om0kDH$eD=}Gx-Pkajf;C|zxxp!BM>J9?1%)TtPI47zS6H-1#=_YtT4!sWAT67zMZVL zvcMD*BQuYf-5!hxG9Y^vb^%sW*0abMsc}spPrXmfJlxW6j5suU z0!&J^ShBebGysy?(`+Ipx*R5)wJ>O!)sWJHKCIOpSiW?m4gC&2ZIIgJR5*d9698h3 zcP5xpl0qKCZ2BNw{uo7H?ijuv+=2UEWw#=Z2=R9Ac>O#;?L+M716W<*pc*586Wp%hSB*jB-RL%X z1FTkj>#5dP2(48JgR8>kIEi_@0_xlAJiZ~TG5lGq{@OO4a%ZX@z#xYH3%1SM2{noP zI=5B30d5?8q7XRJ!L{%`JofrrDdjozt0u$etYiHfeTs(VVFhEKz^{^m54iu{ zOWs<={B;v0qX9tO|4dqKw9%x{E(fb92*anKHE2bQW+auBK}jS7lazYpqY=ikHp^V2 zeN}%)@VNy;!H=5xBs1!2>?9OYTo|-zd7A#;8KGht}(4Z3ZATA-*ICqzvKJ zchlwD-43^ZdzYbj`g0WMKU=esXghHI)XrroN&46h4-C??xe;JdB~T#{_8?o&PpOaw zfYx}NScR11mK$rBNhFVF)0D{8V}-m^@*mj7R@S^d-l(_(&>QWo|Nh?W-6RD@jWJw{ z*6sJ&xhB^JQ%==sSn9%6Cuf3RmIMa)XS9zpH_~xvh{X5FRl!=V5a@(j9Iy=t{lyGv zIR4}_0e0-+BQ0hDOzl?rQD6P=A4iqUU+}J7+ER|PFcUQxOub=x&kdOWABGm5(Cli%_hW#&N;Vg_8kZ|8&+( zv|Z5MxB^WxjlbU`}v&d$ikzT{U2 z6iS2f5>6H3*~@wjCdvf z?jp7#gRMKqq8#~!(QST%YIC4afI6IJg-yayhxO<%ca5dgDLS-}l=t;t`uOG2v4%AW zARr+$ARw9leFRd*%K)@Iafgwi5iSYYGZQdP4mFE?GxMR7uvVaMt~o8rZ6g{us$)zR$Tofw(FZfd+{rJY8-CLa7n&Ujkl|Saf1bb$U>(-e_3d@9ww^ zRt&LzvX2q;Dr&vZj}$ z%jT=xvWqbtVI6cLag-Fw>T7wnCgSjTt`9z<=ZD-oH3x{=M23p;;*#KStm2SJsWg&= zo{Hi=mZK}hgrCt^s>}){xP#;<$0V%w?2>2)zRX3?LAOZzB685bB`1V7f0%MqEV+{EO1|3!wUF<369X*sz~NaI8L3K_y`{YI#+S^ z;TSC0DFW`4erQx^wS$hdh+OQ%4|4>9;0h!_NvCWVMoVr_wBcB3BZP;tz2ry}4n({f z8b$LJ-lNAw4`(O}RT@)5ftqT;VRvg$q5sz-%IUnxkV-!&Nhv99+4e4dK}l%^OcOrG zRSL+aOtdda-JntI?gIf}vpA~?A7{g_zCjVsDHWqeOJOpCaiK3-w<1$bb&7z(MS(nvHLr-Zf?A|^ ztQ@_j;FRA{f##>X#d@OClrK8f)%D_s}^`8C!UmKBy`;3b!FF3Hipwb2CaHg_gRTS4&l94{4$sBdOGHcM3DowsxIaf?g8()^Vj=c@iH2D5#q|YWYZSQDUWM znYt^8c%vmyd8wTui!}92KZl}NdrM$r&#@v#H3z99&jrm_Ei51fM)#p}<2j=!!0ff( zjzoo6WBeEX9&UUUuF{#@7opx)o2LF5?O=;F z_rZ@>Ox@ELz#3Hw;dF_s9X3$k7q!Z&itmT-2EwxHi@%|7KW*%Dbq}Bm$&;$J${mhn z#w8W=(R6w3Qsade;}!C_ZEOlGa}4st*4xv12tVFbTlB_1(3p#(olXL_=oNM{9JY$#a2|QTVwl zj^NP{FG{UwZ)-y|^8zSOba=Aj5G1hnQoJGqdx-lvs2qCQ(w1jddk0_SjrMsp_!z?? z1HJfqXLjIcD%a2Dijwm=ah*a215~&m=iB>Mhe24Pq6G~mXk#1Ku#x#`ZlJl}vve9? z228#`%gT->FlL1knS=gJ?eZI+dJJq&?UC9{>_O}jcrzoAQURg}EN)ecM7N_ve{(pdd7_}~(Pg6o`jTHra;X1}VBJ!5(SJp^ zR(wXi(0mbng#sdaI~iFD6p#Z92)!Abw{L%46ARDmV(^kJ;SJ*ZnQ_Nb(a^Z9G##jPHXK2(5Q^ew%)1^#Mr9}q8iOo3@~+#u^9B55PLZl6 zNC`6$Hh_tz!|TqGY9LxnW`%ut`g5JFg{51Xx|K0^*SA z#^wHHjn$&K&+K-5%{&qZKanq*Br>Am_E~hB+ijScjHxOkWJh9YBqBCpC}ThQs&U5d ziZaPzBBVw+90`!?D`ah?*xnXWB9jNYheG8dFy$`#R$IT+q3xpKFLf~w{BwB{{*XU9 zL7db5;%V}87ik-tp?AHJ$H_S$1PIZKd)eh9#p<-dd8Q5^e_!R#grWOclBNj=zR4t& zB?dleb0&~e1j07phe7bnk!)t+Nzk>QhyTx;iNZy^J(l&aH6ud^i!w>FNipGed4$|@) z;={ij=ydhJK%4GC7rpVHGT($qB8+ECsyhHr;yXYGG^-i>yt@#;?JByRb*;q8Bh`eU z=L5TyhXhcC=6^G(lU7&-I&7S4$!~O;UqinM`QD(s>;;h*iX;C|sp~+e0uf0(n0Z*3 zd-(Tec0e7 z&oxZB(d(*^=CScj)Tgz!pIA!cKg)*3w_3H2(TcR3%$VqlVRrwxC;QD}9{C}2Pa5|( z&^aU++0RqN9LVykrM920Ac{p7%)E3SE|#zJSL(@ARRV#t>h=+etU5o>k1(=o`3|?X z=^wkxF?bC$*t{;npgHNPI!XR&A zA8Juc^~;5RXbEpsp=u0+Dl-qU26;(`e~13C&$m^mlmfxZq}i}jBAeBVj3WWZUCIgZib}Fc6n{IOB@*l;un=52go`Qap z4n~Zy_|L!*!XC}w66ISVr$GQHL&X*aLiD6>7%OkYV(MJrK~^cT*Y{am8HLN=C2Jg% zr>A(L{H-(p3hNEl*M1TnMU!JlL^?RvPGDV41D>RfLH{1Z?p}K3QfOU4mz4GFeT;$t zh#G=QIzEEoKZ4^2Y1gp)qFwL=HimSr#!Gq$g=<4C&9|Kn`Sv<7x8jWxn-K5o5yG#G zjf+U+{jDWvn9S}WCI}}V=r=ci+1Cd7ge^k@?<=56>jQag6kqT1Po1*IfF1=g*Fzly zQKPTdhgH0i)rJ2$LxiF=dO`TV-~y$a6UIVPWUeA0N7e2>W$ypveVC6*iCUQ-4lF&f z(TwK1OU=NZ$!gVC94gvNXQmR{xdgCW6L<0?Hc+OEpW9n0zSA$kW9z{q^>+?cCydNrD z4FPbj+6FSVth`I@61vCmuGZj16#AQF9dd{gr!PikX}X`8Na0_ZR?asoPkDU83eSdT zUz3) zTx{Sn& z-mtqTlF+lMu}2!SV7@#mD@m4U_o750y7hNZKS}*ne(MXUW4i6CB(q{$4KKem9zdxs zg!mEL7?gAq$dS2l&{q5xM!OOOSCVOu>l-{9vL$U%2Z6Y&V! zm#}_ljpk0*k}du30wFdey@>4BZqTSzs}k~RUF>FD%6NvUW`v=hV-3M7)h;V&wV@b9 z<}ue{_$tTgGH!Wj*e&JZMp7o}fVWW@k<@=u4CTLBTh!*Qv=^vFXmUtNuyO=~o-$Cu z?jO=N6fw~ys?6y)w4wV_OF6n*)q7NFE6^tjz2EW zw|PgtQ>4v-BN4F$78e@JN3;~yzT^g#E9=+?q-dwIf=NvhhVgFY3?kwu0ZPeRAh)D{ zUr}Ag8^BI7=;i|wdQ>KJKgfoE31|wF^I&s&$ty#>7;U{uy+Y6@h}TPFS`nfEdwpSX zB{;)@kDaRjg4P@b6{G&4(Uf+jo|GtQ_Q}Y8fd1cl=MXBHY5ZAh|HpFOPl!JF<#Wmc-H??& zTo6o6Q;HiS;3u@ zm6-?Bp}dEx#MGJqVbkxcC62 z#!O}|pBmQg{Z3EsDhVsf)Z!|Lm(jDF_&s3Ebiz5O|85Wn0 zjV?Yk*(sMNP=)*Y6y4rPi|8s!7C>y8KHeWp1C}1AJN3)|n&t|<6Rcf7(;V~1)=B7p zRxtk==l;c5hwNQzRIs zxM3g#jv(j%jUdL`xJA7BRY#PSGm-JybD!g4e)K#RX8?qL!x{lu2yINgcS4km*IF4B z%Ge^;P5&gT^L-F0KIrOJWPUm!-%Wop9%+{KCj@YwakZ#D*oy13^}SwI|tdacuBI{}bQA8T>2Z9QODR-7x#H`s%KJnhw4ZgH0#q!4Xv zhr^m6L&L(7RBc-V1&2!TAT2 z-S{z^MO%!(Kgd7j)O?mRxB;b`LPh&SX*3qo!ZT zJqho6P@)q2akE%qo5VqikT*a*(= zgOENPB^tnp_=6nBd}p`AKh56LOE`IFtI~tJiC{T;vSf~suzUnB1o6w2{`W9YBr!mo ziIghV|4b`^a+J$;AI!y2={?r<=ng5g$9Ruogd@&LP5w`P zP8-j_lmn(6-6nr)-OP(+KGluLm|)oY0h}A^iw0tbf7y+V&>eIru@B$pc6PBbq`pZn(^&P?G@gbC7bn7~6wpehjyy_XK58vZ8w#mtEV?7coGb9N zW3L>RM8|eQM@coRqQniMCBdGOVjd*GjMfM?u4LPF@4p7POIH9%`A?azgZ;mkR`_D@ zB)T$0K#Jx={gDn(e3L=Xm9W*9cQ zre)BKR$dYuFQ57Utb{nERmSGrTeDr^qvC1+y7v4DKi0OqPdx3J9`IUa=eVD}PF`X8 zvSQDJbzrTTn=SG+mQPIT;9rqit2XI2I^V+zQL#_LDopx@2t(5}|4yiSO(?M|sBS#zbJv|G9Vy_V8)mvTru@d*BpW+eav=EnmGaT&{)QU*gw*i_mD$nkIk!HGJjyr%XhIoE zHs2Gi91XXc`cwC>js>=i%BNb2&|1|Kn;Q*(Fdtb$7;7|}IiQ$1!psc1N}8CsX_XwKeNIeM~SakgSYl9o$P;P}vG0Sx;crlV&#?082%ys4K=jZZK3NNk8W<$fF`P zV;I63bwEAF<~4ct`CkIJ&+@k%cSFty2(wHky?o3#mF7%#L+pL#Lh62)py zxTcKcDkXv@U-Xcf{!+fxUUo9CHF@fRhxh&~m2P%UOl$dfFuep6w^8UT4?@=9TK zdrj&;Tsijg@bimfWFU4$VA=sVRO7-dTa-j@ixOD3=93S>s|{E=s!}Sl_+auUdn1&g z;8rIJ@_z$*`V^a;iW)H{{uU{Aa+F2E%nq#faVQ4$axoj3GW7B%W4b3}JN)=VRtP2^ z@c8vxqM4tglsfR#wpF%ygxH?^@Bh{EW`;typMP4O1tbuV-2Y7W%OiZiu$q+0e~5hC zFjxaXzlez2h^?7vp{g3fm6KuAP?bZD`Ysb>L*`7$*)o7MzT+UMz$$rPKt7QEZNlq! zc`8l#vs56;#Y5xrPM){A0=7Qodi}5cyS-oxfjtIp`U!*u#SrC!AyRYX!UH88&LX;2 z=ck5R=%B&2J;r` znng%4&bU*PZdH-&O(-7&)5zR56$#RK)Z9*?vx)peM5H)oa>4+&s_;EpBFzWlJRZ1| z2F>Y;A0j)EZAP{3-&15aeslr6D=^(3XWht&HepOFS_R>%zou80oGp?Ox)Cc|ZqoF* z#GvRkumr6#RVm8;BCP~bG1>IrK`H3%$#rn;^bX+Jaz&Dw)~t<1S3|S~bX7bEVov?j zsdpWxj#xu`=Uo81jA|nunzz_S!t=l}zD2E?v?;3-a>~NMuQLIInIv7(KnDt{FeR?& zF{5n8WlmIg#F-{_?S?lL+8Ms;JhrPXT)5$@qdTX_6h*nEX|-iIK(%vlw-BuX0757 zkXAuHip>RlqD{Meu9tTK2pV3|4NxZ_fe%PVZ$nczEFC8>;4iZGK#p)LzdXqC5_yv7 z{jOxe_m8)5!c+7R>XWs5`l2EUu+UGcqN=>h%yflu{mdpr*O<#Mi;fQsMz$-XgV0Ri zg3R`7`N(u#uO7SLk9)3^i#_1M#r^JQb?gDNE$6Bs<#N#6{Z~cE(W-8-} z@vTJ*;nV7uGlY&XBH1}veSy|LX)2#q7TRD@gQX7B0PRkp`9@;@+EBXJYd18Y8e?DsrX$4K5NI*ajRR1fXU`o3A z0|C(XF-%@c`OYyl?-@G)5hnagD1AUAB`GN?C`pJ2Y#9t{jf$;!mNuDYYRHUYK`uyZ z?YCr6vs?&P&#zrvv;0O(G@`MkUK97YRHM^+w(fp;wO;1d8p-?Qam~w|1S{rSQ%c;hcrsxVj z>Z2Gfg`aFx8sLnA#z{wHFi{Q_R%6e-Z6>DvMxtw}J@=Lpl=g>O-l?0oN*O%I-kALe zGCPMF8+0N{8S}iYX$iM(?5$m>gk&rYSz8T!np2w;-iVnI5N?5eX-QvM*9YhmMp@D% z#Y{jKX!2@AJ87``cqvo`u@MOXiZMr=oAfGI%4#q*^nh3>-^z+AiL}nx37(YS`Ikeb z$=&sl*)e1f7jk*{ zLQPXH9`g(_KxeoV4GxK6qy*sAOV6*L66G>$xuc76Y$PWvjUCZv*-8xew5;i0t%7U7 zJ{Rl;ETM=HC-+xA#vJ6hjG_x16M=n)2ArPNs6b1ROLovCZloNo#LWv&-J@|T&XE;d zVklv;FT6%mt!o-CkFctGGU(BgZ7$S3w8T#-4J{njSju#d8w3YTZ4j_nTbjZjMN$Oe z52^};w0}_qI{U34*oL&HpOR9uU3U|RHNF@n8=R6915YC@gv5r@kt&JMd-pJ^X{pQ~~& zo4LQSZyN52`vwV%2vM&t89`(iSFwOSVJy674MEhfH><0Cp`&ci`wgnn2s7gi%X}h* zkn(f%)EL`*hBm;Mr((9nSn}t~%LV#sapD?NZN^enl3y^^s{qWj?PVx2n?L&hLU(TT z(HA}&%A~r!g7B+}UiYDLTp1@Rm;SqE`dJ>ARg&95GlxttbMHdVS0;yVkzWnsV`IaS zVQ0J6N#DLB$bCo}?fhlu8J|zR>CW`-8;Vo=aFRJ$n*NQ~yk!10G$i7g4h?=`sMDmk zZ;~^fB_YRK+5%wYK(&P&_F-WAXHuxqimxqi?2!uQ2mXc}69T?{SiqR1&Vl|u`^WGg zB48cUrQ=De;fgOsJ!1xLgPo=^zydTXmc}AEBXtCTkUP>S9Rxt0#Ih$_>^taBdTCF* z*^Gb7)f8Q6#JGV0VaW7^Vkm1yY7zwtn9)Fi^py`2oCJIwi#iVbl<$ylq+M+5D;d28 zR%STB7D2_e5B4#DO~g(l)kDfW9%p$j2d&(uMgWHYV5vs8n)>i_*T^n7FV6vFVBof7 zDxYS9T2sV+d`UsR?f3jrY)BS(B*jU$jz+FEzocQ*cwPy}`TGbUC2>UjfnNhjIPW#@ zs->}R4FKd{I%Mh6nI-PUWEU%`ZMPD?P@zB8h74{rsOKx*KD@9ZFOhI|7m3KuNKgP8 z@Gf=@ou^m`Ul89mJ3pW7FN0cOQ|K;9svle*@6q~Ymt*`rIrMAz%3L|D)6E-K`kuDP z^o*G;Eh-3DMYNgI9=k={tF$)-Ho}V5O2sAo;o5w5fahpm zITJhoL~-9UPDjpRmkBJ4B}JI56c~{K?FM|c$()IZM@6ejP3_oVPU&dp||`HO_i?s{(c(c6ic+ zm?}&~%qn$@^H-a*+xAU1g-3?ZIdhWvz*WV(3NXN8ZTPwlWW)G8VIlEhw2@X_SLyEIL|itv zjecO0jwfgG7U3rpx@_xdsG+7eEcplS)z%HKZ#T3y)||)J{z5jPmwC|`Y+2K&_bnEI zyYSM#QjKXd2w7%#$A#O8{nF9bc4~SSU7G`cOo7}RykK+QbWsd;_toXA9-EQW8W4f` z7JeneIwsTO`Cb)EC6s5cQWD#VFRhB&42M;XBtS$c?uzXt;w0BVM`mPO%ECe;e{8sd z=SIN7wNW%Ylyw1SP|RYsS{A11VL?2}jQ7qm)ET*rgu2`i@rr1n=P}teie!}pPCtU( znYnL-Q33Uq=;pUvr+~Fyb{2Zt1qfdf2bolq=IP&p4T*S*u#AckpZ{~M`rMZ=%}AtT zm6|_><2y41X(VM=o2TXo+9-qYnhqQXd3u6@FS9jpgLcPjJVVjFIEZ zDO3G^avx3LX!E*n%)EE^3SLIL!<}Z*LQCo(drB*pqQY!K zAnn6=UQn!=rtV-DS)N^7j$4r`rs~eLZPmOO@6LWir~@_S4+!!fFTs=$IAVV^(N`HW z`Fkl+l8+JPqolJPcPK|zG9T55ZT?^cHsc5XrwG9S`651TX+yi8MbqGv_MY3vu^;}` z$v?`w(Sz_0!58^(M}<+`=Be8egwJd{2#VyXTO#Rv5M2uWpDG9gvVL}C-C8Jf?;I}} zAIC#ojp&BosDKqp?LiyQ*TXi&dwqpcmNC~Pb8fK(?rbOJ$VYBHsSc^QoueE|!pEB8 ze-WGhw#VXIU#wb^s;A24K6-vH^62h{*@=gdf6AK&8TK1!;N+}^s2CW|NAXZyExtT_ z99xNdIw7_-X6RDv|8znKtOof0;W46D>wmO<`2s)Q%mxJF9+pE~5A*)GE|{&brR2IM z~m+WP2*{k0hmZ!3Y=i8NqxGNj;yq%VTmD+GE? z6bZrd^GGXn`qXM z?a-OgV?CK~Zf={}F?6C?#iTWz+_;kfiGJJGo(=F?2sh_DKkDGRZ8h#9v`CuHhiB5~ zpnI28cbp8t_R>|qo2p=@P6+U=O7%A1@_a2~{Y!mxjOt~eK9QClbWGYOrozT7Fmw19 z_yBJJ7Q_Y4meFzg*N@dlkK@w=3VeRJ1BBA30muftV$o;$zc||KGEOoZ0bO6bzYm<; zxubw*wgz^1O_#PFVVI(!`ZOR;AY!J;&aCn6q(Com=Nq!%Dd*nbe0(OB8Ji_3}1W>E)sl9zf5-*q!) zOy8r__F|9+wFM#xyi_Mto}g#ueER#6|0B0bG2~m-IFH1Wa*fC60Py!$7{}=O>0n+1 znxEK{Zdu@BFI85GJ3W|`c4yL(jxJA8Uj_4Pzu${zt;@`=2in9}0c`^5gwSCKKQ3VT z!uvL&#DsL>mXw^s%tahGa0H*pQc2BfGoL9@#soT>kJ&i-VEDqhl!=vVPuQe7><`Ul z!beyVrZbcL(Y1nR96=xkLJ?-1Av*rBHF0oAwoB#hI)_ z5Lqf~Qrd0iUu&Wb*)1li^nL zxr;+HxUn^L2_{TfS;)+!f>_WR ztl{+u8;|&BO9pd>M_>yqTM(2cP777{2^~QFSp1&-ik^K@vD?}4&lb{uI|2D1`j_ZC z>EN!#*=Ycs>3taNE%6wAygLr~b~Ka9i&nTqW2E~>qspzY9+5qd#pk@YuDndZrPXbw zan1FCzHc!v2$xxL^Q(7{zk8SsASbp>-q0JQ+!Y0_p3?3~5Ou3V+kb8Oef^kA^POs( z9jqyqEzQs_InV*atwX#illxdFS~y>FsY#plnibfe=@0X)?&Zsi3&8|fj|b)g65$Du z&-$PeA5n6nu~~vXjor{}NKY`pY-){Fchz0{v>p zLh3tq*jeu~I~%WnMYOr8Gx76?zFqS%>)_99Msi6v7gnu^BhH;#0S}EUDY`%Ku@LGB zqgl1wn9Bsa`j=(|RT*eA$+$-mKIY6q^297XE@zlt zhhflH_Po|xFP=O$TN5*iyv`Rtiad|ocYFS8H`B4_m(3Wc|IT4g>vI8C{2|^yBmOUX zLzooPj|H&uKv}`^uSJiei;JP_Go<*1guc;W+dd>0C@TvWU`(8aTILRW%B&g0D~eB5 zl+fQKm1Te0<3PH_(RzFn@PJBr==!>x`xWYco@eRJ**4S7l1S$B!%m#*dY<;#KJ?0a z&Zz?MzbqI4Melep1tTsa&LN2<36B17$Rsgfc>sC*KDP~A*U+qZ&9)PGD3H&OGnSU< zC#uqDE7ZjbIENupMW{icjxgEv39^BVibAo(jy;%8TzcLvOIpnOwwcvQZpFU z5BH%e>@F0MQBk2e6WT3Qbv2sKHHCWoJ-nCPsX52;?o%k;(bgxMJAUh~CMP#t*R%B~ zdH~={vQgTs7N2F7Rm*S)OUu^2r{->_QKr;J^^8(?uTuQETT1*Qs{6`w%zgQu2FW1S zB_#{#Tui%ReNxtog5m)bLenAArP?yWX!1o44*rB@J){X1HqNiBu-6vGVCgbXJgV)DZH{9pr*~~^axnLrZGQcFXs(3_q9{j} zTnxw(WM?P&QC9tY6D=7Y3P#Kw&mxR%T%k-P#P0d|DDET2+za=prC2*tL%J>XuHt=? z7s_t$8|ZAPhYqxHDtJHLuz;v&GeD1JXDHcN3(Iea20Q0ON852cn~NW;7WGB@wiV3_ z52g-Od)2|>)6oMw#7F<`)(j7fHqn=~qpyIlOh`@()w3&>?jer@TCFsvi`#*EbjnlA zuoXk}2ZU(nFv8dpo$eaCa1mizrJNYMv`5~NrAc)Z8&t!aK+bs@SsTue0qDvPJpaex zxhfI0ebcjmaCR#VE-;J>CC!S)0mpurDBLB6T5TS!cP&yrzv2 zZQqD0_O}>nrM6XE%ur0Bj5{N$={~lf{BvDY+M>>Dz+IyZ>_UL2jJK2ccG&vuB?a$v z7ril|25(1$dava&M!U#gtk=Iq6%XrMFO?kBFNcpy@$2LuoTvQ?z>n(iQe1_TkR5o= z!4Z)kb1$xy%><2x&ew6kr_*LI^`+fs>Z6Hmdpj|3KH*xwHYUN=Pkm_e6cS< zGW70>>E!hs(r2R^azj8M<25&(e)OtIl$4eF; z;V$9V9h{tOOumr(0b;x*x0TSzi9K>Le%7n54)|s#3Ey$~z%$ktWYBm|U-Eyr8TX3E zSTs2qwIVe#0@CmV=?)d@lD?d&`bJf{YTbwN1d&_hj%L^c$TT^^7Ippd&A?(7@C7pf zOMYPU&GGaNYM3r-y_b{TF7yRTP|H02PEv>SVS5_^@sh!xXPjIDIG*&1P7mH~@D6T3 z0wPGK=USUm!wKTPunO886Ep04gDlF9iIp!B_6VHbO1WuV>@*Va#Bp*BW8kZFyTXzE zn~1zl@2Nuo9xt|u{#QgYWJs>ck{_!5L^744$2W} zqy$$`SAW4zWZ^eQLbM{-c3(6hIjmnsl7&;txW{5SEai9ToX137>G(-} zpB7eq@s@llRcB<$q;6$akYYA9wLU#w#NoQ=Q@&`a-ide9NmA(J|1wamK$UI|{w@~L zdic@?Ab!3e`ELqJwBMr;AmZ)5&q9tA*)+XVZQmN7@85KM5YQ@&^%&2liNHF0GCz7; z^g#H~>qk;D!%LoR1>CPJ%CWJT_Bo}TlHD;Xcm?$9*Me6*vdY+4@ncdIMGmx~od7 z3+$I@10~VW>@{e!EnrJAjW+7~;IR}h02J^;4JCW{+ZL=J`r4tUtWj!{#q_JsjeR$|yGcx6@&(Yi*TC*aDym=%pW0RQSt0QS?N;0%fK@#d8s+htN zMLf&YLSz(gRDJ2c#MlJQ0nOgpobpUIwF|$?4A#yq-CoOv257XWQEMo5bdhj!T|k1} zsk9tL95f`}E~Q;fwO4N#Gv*L?lp83IW}<{mo9-}$WPQ|IS+<5mfgQ{x=2Ew&8(hW- zJ&I&o2(*zNag$XM7HbSSvS!}q3at(v$~bK^7j>5&fwfm=XGr70^=Ti2LrP06h#Zmf zb}3n|^S~Sc19bnaaLf|cDq{5+vKe^OO6F6~%_6VR?!DJ4?W~t=daMwUCst%ODV=37 zuJJMJs<@|^lD_lA2%8bvhO%x2iM{^)@K)g39-hD)JR^7aVH0EU%9=33joxrQg-W&- zr^%}3E3L?X6uJtr^?=uK)HAxOV!nlthy)mF=_t`?zyk97$sJNs8~Fnu>Ys0VQHseP z`usgR5!cHpsHh5rVFiigIRqp??4S|FFDw@+%mVXQ<`r*_DF?nsg44_OZqI1*xs#dl zHsY4Z3=;UV$t{TPYsOpPU!qVebpl?`56mY5C?9q!8%!|YK)lAJim>Qz z17QZ2=zJJQj$B3wc^O_$8_xM{gbI8d9?k>SEoPoii?Kb2Io1;)7(emOx2tl;xzknh z=xT*>(2W=d*jS;7>FNJ983b4NERLIsOyd4Qoq(BslAEA`iT~Z$>qg^%kTc?V=pzre z5laU;8HDaDGPC3)2kzFmn(Ylh+!RF9%SVeZB+A%H#~Ta}9uSjVa==iW?*` z7^7fCgUkq^Re<8f7)|%H_o_(x(n)voP_?6i-$id2}_nd{%DRXq8VU}p7 z;Un0$BmcyjE_9H1!(u#s6Zj3)?Ja~^0X*?+h)6=4mD~Rvf?R>~-ffkt6W_(Sy=OfJ zvSR#d#&Sn_8oB1EOm`UXxjRu_g~9!(Xsx^i^3h}z7>;F4|D++O&q%RhX7PI3fx4KJ zHLtTZHYc?=8Xg*0{Y|Vc@q)cf;b;b27P%Hi<@yYh`6kMNJlk&N%7C;bD|lQsNBRkx zoMEH6^2GChdzX!UH*4$IT1B@wKct~K-L2xw7nQh6f3aKteN&`Z$2P0(G^&{Q8E;85e zMwV3?7$h{@v%LLhuHXk)H~0`1xDd=2Pu1$C9B-?&JmwzBs!DpY5k>ftdM5{%Dja-q zF-y3T@e#yzBWMjG$oSAAyh?Vf6!^_70WS|PiKlMWA<>vm>p8m~{KxWrB->8S$O#V8 z2zklyk}gQI!MmIm47bUeZq*&mrMz#n%-=cR^~)2m`5|=oYz<1l6Z~NjZb@9`=H~xi z91+|t(7`U!HTA=G&%AboHMqWbDi&%N2aboUsZ~fcsf&Zy6&v(1i2$nEH>gTO3HG4(Sd`Jw2?LibYHcKH4O|4wYAmg;)+pvuRT*wT3MmZd87y zdPo{(q5q?!pg>n$2l0I)qOx@RvUV-E{Zii;3YvvyQ)9;APx-B~Z&N-FFx3`Yv2GwaY~>d11{NQ>g3 z9ymGdDJy8xnfF!x(ha|2$m&c`UYFVGg9?^JM!Nr5A+;2;R_AOOUn zwYFcys$_{N;wL7!#V@)CfyESt6v@ZUMv}wzeoLZLdPK}c*t(I+-$x;Y(D9w@X{`o* zXd|7Pw}jB0qS;T%gwiaP)^7MTfN9s+@H>|q8%O+*&wLPcVlQLura6!PwTvtWfh*U` zWT(Jn)N3FG_txP3ZmK76%T{f9K3^2>x=1t6ofr{-W^^y=a6Ogxi05PT%5^Va+@fYT zjg@Yu>eGV1$S#hwi7)s6Q`WfvMOB3X`0nN)%1a&wEb>S|5s=4%E|U$g@s!NeNO`C{ zMgdb0lpF|Zy@ZZR4Aim20kfK00|pe2NK0@mA7z0&WMP3_1mv*+661`FV$y%ly?gO& zXJ+T_-uwOk`OkmPx%b?==lrKIG%%w(+uWh4(uTa(b z?1`0>Uc4_GFZHkS8NX$;H13|s!T4{w9tJlIzA_oAsE+!!r1nX>Q~U#JWT7~EddymT zuWV*=?(fO#qXA9I5@}HO)(_6L_9#Y*-&dui9GG&5PUx(#II&yx#YlZ}?ws^&?q@^4 zHIy{gWu#4flD;znS?rE4APR|m3+-M0V1q%-SP)0Ialg-LD9 z&dt(__R8ls?qpqX+55@Bsjeau`(M|-ck7WlCSk+AnZowg*~3$&uB)Z74XIB>@lOh` zowIn>{d3VrPX3)HQ>$b)Exk!rABMEHg)7>JhM4l-pNE-lI$1Z9H}c~#I%Zz=?CaCb zR{GOF&0>qZ(5~*Hm0H_O5nR1QVyl;yQxuH8YrdSe6U}w|nXq3jAIkQtg#L0Ak|{SV z!G|)H5so zWB1vu(ASBQ;8;C-%n?=S`05^sXd2z_ad2X7(q+VM-Gm=(wh}Q)>UKxoy?j1Fy%KRE zyDz|l%V%+bRe8isQ5FarLD?WYhL9M#5w-NXII0S%o)iUd@`S|DF-W9x z#Ed*mcJ(+Msf7=qLSpDgC`iQ_{8N9Odjb2-l%S^?V_dqH z%p7kiJiEBU4Mj@8Y6*tlw6jIahB&w)r>=>G2LXPYfD`O_*a98w^T(RkEkro)gIm-# zTZ-}_V6hVqo1@7-3k;vl-LvvCKw9{~7&IY)e>^c9(7y_UZv+PPG4Py~2ldHcz}Uhy ztY<;X$fTob@3E?U~oJ&c+JqDp0EpCHz z(CGZ)IcIYj-^hc@&_Dg0?VB?EBX;mEbS1RTLyrplofu+_HV<$vOiuLc+zMXtw4*3* z0xpHHUjUa5ti~pE&CTUAP+M%FV-`q&9=kA@vBT9^H-Q88a*g{4g3auP(qw{rk?M7td&^PfdF0dF$haMpqdG;d^j9BxH}b2 zB&l^94X``%%CSb8K@P?-y#f9O&W()F{BHq^02QU9V9U^V(Ch;# zI$manjK(?NFV4B2Z0*0TXxPo$27EkoNVF}z delta 50109 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 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - # For Cygwin, ensure paths are in UNIX format before anything is touched if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") fi # For Mingw, ensure paths are in UNIX format before anything is touched if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" fi if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" else - javaExecutable="`readlink -f \"$javaExecutable\"`" + javaExecutable="$(readlink -f "\"$javaExecutable\"")" fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') JAVA_HOME="$javaHome" export JAVA_HOME fi @@ -149,7 +118,7 @@ if [ -z "$JAVACMD" ] ; then JAVACMD="$JAVA_HOME/bin/java" fi else - JAVACMD="`\\unset -f command; \\command -v java`" + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" fi fi @@ -163,12 +132,9 @@ if [ -z "$JAVA_HOME" ] ; then echo "Warning: JAVA_HOME environment variable is not set." fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - # traverses directory structure from process work directory to filesystem root # first directory with .mvn subdirectory is considered project base directory find_maven_basedir() { - if [ -z "$1" ] then echo "Path not specified to find_maven_basedir" @@ -184,96 +150,99 @@ find_maven_basedir() { fi # workaround for JBEAP-8937 (on Solaris 10/Sparc) if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` + wdir=$(cd "$wdir/.." || exit 1; pwd) fi # end of workaround done - echo "${basedir}" + printf '%s' "$(cd "$basedir" || exit 1; pwd)" } # concatenates all lines of a file concat_lines() { if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" fi } -BASE_DIR=`find_maven_basedir "$(pwd)"` +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") if [ -z "$BASE_DIR" ]; then exit 1; fi +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + ########################################################################################## # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central # This allows using the maven wrapper in projects that prohibit checking in binary data. ########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi + log "Couldn't find $wrapperJarPath, downloading it ..." + if [ -n "$MVNW_REPOURL" ]; then - jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" else - jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" fi - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + if $cygwin; then - wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") fi if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" else - wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" fi elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then - curl -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" else - curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" fi - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" # For Cygwin, switch paths to Windows format before running javac if $cygwin; then - javaClass=`cygpath --path --windows "$javaClass"` + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") fi - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" fi fi fi @@ -282,35 +251,58 @@ fi # End of extension ########################################################################################## -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi fi + MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" # For Cygwin, switch paths to Windows format before running java if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") fi # Provide a "standardized" way to retrieve the CLI args that will # work with both Windows and non-Windows executions. -MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" export MAVEN_CMD_LINE_ARGS WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain +# shellcheck disable=SC2086 # safe args exec "$JAVACMD" \ $MAVEN_OPTS \ $MAVEN_DEBUG_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" \ "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/mvnw.cmd b/mvnw.cmd index 23b7079a3d..f80fbad3e7 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -18,13 +18,12 @@ @REM ---------------------------------------------------------------------------- @REM ---------------------------------------------------------------------------- -@REM Maven Start Up Batch script +@REM Apache Maven Wrapper startup batch script, version 3.2.0 @REM @REM Required ENV vars: @REM JAVA_HOME - location of a JDK home dir @REM @REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven @@ -120,10 +119,10 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B ) @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @@ -134,11 +133,11 @@ if exist %WRAPPER_JAR% ( ) ) else ( if not "%MVNW_REPOURL%" == "" ( - SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" ) if "%MVNW_VERBOSE%" == "true" ( echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% + echo Downloading from: %WRAPPER_URL% ) powershell -Command "&{"^ @@ -146,7 +145,7 @@ if exist %WRAPPER_JAR% ( "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ "}"^ - "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ "}" if "%MVNW_VERBOSE%" == "true" ( echo Finished downloading %WRAPPER_JAR% @@ -154,6 +153,24 @@ if exist %WRAPPER_JAR% ( ) @REM End of extension +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + @REM Provide a "standardized" way to retrieve the CLI args that will @REM work with both Windows and non-Windows executions. set MAVEN_CMD_LINE_ARGS=%* From c85c517c5a699efb5fdbab0349954dc4ba4e1420 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Sat, 18 Mar 2023 14:49:44 +0100 Subject: [PATCH 25/32] Fix: issue 3951 ConfilictingGenericTypesException is thrown when an Object type is expected as a parameter and an interface is provided as the actual parameter --- .../resolution/logic/InferenceContext.java | 19 +++--- .../symbolsolver/Issue3951Test.java | 67 +++++++++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) create mode 100755 javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3951Test.java diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java index 183ff48f19..d91c7950ca 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java @@ -21,18 +21,16 @@ package com.github.javaparser.resolution.logic; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; import com.github.javaparser.resolution.model.typesystem.ReferenceTypeImpl; import com.github.javaparser.resolution.types.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - /** * @author Federico Tomassetti */ @@ -79,10 +77,13 @@ private void registerCorrespondance(ResolvedType formalType, ResolvedType actual if (!formalTypeAsReference.getQualifiedName().equals(actualTypeAsReference.getQualifiedName())) { List ancestors = actualTypeAsReference.getAllAncestors(); final String formalParamTypeQName = formalTypeAsReference.getQualifiedName(); - // Interfaces do not extend the class Object, - // which means that if the formal parameter is of type Object, all types can match. + // Interfaces do not extend the class Object, + // which means that if the formal parameter is of type Object, + // all types can match including the actual type. List correspondingFormalType = "java.lang.Object".equals(formalParamTypeQName) ? - ancestors.stream().map(ancestor -> ancestor.asReferenceType()).collect(Collectors.toList()) : + Stream.concat(new ArrayList(Arrays.asList(actualType)).stream(), + ancestors.stream().map(ancestor -> ancestor.asReferenceType()).collect(Collectors.toList()).stream()) + .collect(Collectors.toList()): ancestors.stream().filter((a) -> a.getQualifiedName().equals(formalParamTypeQName)).collect(Collectors.toList()); if (correspondingFormalType.isEmpty()) { ancestors = formalTypeAsReference.getAllAncestors(); diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3951Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3951Test.java new file mode 100755 index 0000000000..7e57d4df85 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue3951Test.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2013-2023 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser 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 Lesser General Public License for more details. + */ + +package com.github.javaparser.symbolsolver; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; + +import com.github.javaparser.JavaParserAdapter; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; + +public class Issue3951Test extends AbstractResolutionTest { + + @Test + void test() { + final String code = String.join(System.lineSeparator(), + "package test;", + "import java.util.HashMap;", + "import java.util.Map;", + "interface Foo {", + " String getFoo();", + " String getBar();", + "}", + "class FooImpl implements Foo {", + " String getFoo() { return \"foo\"; } ", + " String getBar() { return \"bar\"; } ", + "}", + "public class Application {", + " public static void main() {", + " Foo f = new FooImpl();", + " Map m = new HashMap<>();", + " assertThat(m.containsKey(f));", + " }", + " public static void assertThat(Object m) {", + " assert m != null;", + " }", + "}"); + + CompilationUnit cu = JavaParserAdapter.of(createParserWithResolver(new ReflectionTypeSolver())).parse(code); + + MethodCallExpr getOrDefaultCall = cu.findAll(MethodCallExpr.class).stream() + .filter(m -> m.getNameAsString().equals("assertThat")).findFirst().get(); + + assertEquals("test.Application.assertThat", getOrDefaultCall.resolve().getQualifiedName()); + } +} From 49486c677affad846a9fff4b7f6e01366c2fe0fd Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Sat, 18 Mar 2023 14:53:46 +0100 Subject: [PATCH 26/32] Fix a typo on ConflictingGenericTypesException --- ...esException.java => ConflictingGenericTypesException.java} | 4 ++-- .../github/javaparser/resolution/logic/InferenceContext.java | 2 +- .../reflectionmodel/ReflectionAnnotationDeclaration.java | 4 ++-- .../reflectionmodel/ReflectionEnumDeclaration.java | 4 ++-- .../reflectionmodel/ReflectionInterfaceDeclaration.java | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename javaparser-core/src/main/java/com/github/javaparser/resolution/logic/{ConfilictingGenericTypesException.java => ConflictingGenericTypesException.java} (86%) diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConfilictingGenericTypesException.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConflictingGenericTypesException.java similarity index 86% rename from javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConfilictingGenericTypesException.java rename to javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConflictingGenericTypesException.java index 14cb337139..16c41c8e6b 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConfilictingGenericTypesException.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/ConflictingGenericTypesException.java @@ -26,9 +26,9 @@ /** * @author Federico Tomassetti */ -public class ConfilictingGenericTypesException extends RuntimeException { +public class ConflictingGenericTypesException extends RuntimeException { - public ConfilictingGenericTypesException(ResolvedType formalType, ResolvedType actualType) { + public ConflictingGenericTypesException(ResolvedType formalType, ResolvedType actualType) { super(String.format("No matching between %s (formal) and %s (actual)", formalType, actualType)); } } diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java index d91c7950ca..cc0f76c6ee 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/logic/InferenceContext.java @@ -90,7 +90,7 @@ private void registerCorrespondance(ResolvedType formalType, ResolvedType actual final String actualParamTypeQname = actualTypeAsReference.getQualifiedName(); List correspondingActualType = ancestors.stream().filter(a -> a.getQualifiedName().equals(actualParamTypeQname)).collect(Collectors.toList()); if (correspondingActualType.isEmpty()) { - throw new ConfilictingGenericTypesException(formalType, actualType); + throw new ConflictingGenericTypesException(formalType, actualType); } correspondingFormalType = correspondingActualType; diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java index 9232c84890..5ee4aa678b 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionAnnotationDeclaration.java @@ -25,7 +25,7 @@ import com.github.javaparser.resolution.MethodUsage; import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.declarations.*; -import com.github.javaparser.resolution.logic.ConfilictingGenericTypesException; +import com.github.javaparser.resolution.logic.ConflictingGenericTypesException; import com.github.javaparser.resolution.logic.InferenceContext; import com.github.javaparser.resolution.logic.MethodResolutionCapability; import com.github.javaparser.resolution.model.SymbolReference; @@ -219,7 +219,7 @@ public Optional solveMethodAsUsage(final String name, } methodUsage = methodUsage.replaceReturnType(inferenceContext.resolve(returnType)); return Optional.of(methodUsage); - } catch (ConfilictingGenericTypesException e) { + } catch (ConflictingGenericTypesException e) { return Optional.empty(); } } else { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java index 051dd7f267..fec1caaa13 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionEnumDeclaration.java @@ -26,7 +26,7 @@ import com.github.javaparser.resolution.MethodUsage; import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.declarations.*; -import com.github.javaparser.resolution.logic.ConfilictingGenericTypesException; +import com.github.javaparser.resolution.logic.ConflictingGenericTypesException; import com.github.javaparser.resolution.logic.InferenceContext; import com.github.javaparser.resolution.logic.MethodResolutionCapability; import com.github.javaparser.resolution.model.SymbolReference; @@ -199,7 +199,7 @@ public Optional solveMethodAsUsage(String name, List } methodUsage = methodUsage.replaceReturnType(inferenceContext.resolve(returnType)); return Optional.of(methodUsage); - } catch (ConfilictingGenericTypesException e) { + } catch (ConflictingGenericTypesException e) { return Optional.empty(); } } else { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java index 696ef9d7b1..574637a7f1 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/reflectionmodel/ReflectionInterfaceDeclaration.java @@ -27,7 +27,7 @@ import com.github.javaparser.resolution.MethodUsage; import com.github.javaparser.resolution.TypeSolver; import com.github.javaparser.resolution.declarations.*; -import com.github.javaparser.resolution.logic.ConfilictingGenericTypesException; +import com.github.javaparser.resolution.logic.ConflictingGenericTypesException; import com.github.javaparser.resolution.logic.InferenceContext; import com.github.javaparser.resolution.logic.MethodResolutionCapability; import com.github.javaparser.resolution.model.LambdaArgumentTypePlaceholder; @@ -167,7 +167,7 @@ public Optional solveMethodAsUsage(String name, List } methodUsage = methodUsage.replaceReturnType(inferenceContext.resolve(returnType)); return Optional.of(methodUsage); - } catch (ConfilictingGenericTypesException e) { + } catch (ConflictingGenericTypesException e) { return Optional.empty(); } } else { From 21eb8d99b1fd38f359bde8cef13f734cbbd771bb Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Tue, 21 Mar 2023 08:09:54 +0100 Subject: [PATCH 27/32] Fix: issue 3947 MANIFEST.MF points to non-existent URL --- javaparser-core/bnd.bnd.template | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/javaparser-core/bnd.bnd.template b/javaparser-core/bnd.bnd.template index e087bd0ba4..b4a964da45 100644 --- a/javaparser-core/bnd.bnd.template +++ b/javaparser-core/bnd.bnd.template @@ -9,3 +9,8 @@ Bundle-SymbolicName: com.github.javaparser.javaparser-core # Don't use the project's version for the packages # We prefer not setting a version as we don't follow OSGi version semantics -nodefaultversion: true + +# Fix broken link on docs +# https://github.com/javaparser/javaparser/issues/3947 +# https://github.com/bndtools/bnd/tree/master/maven-plugins/bnd-maven-plugin +Bundle-DocURL: https://javaparser.org From 71011ccc49e1d91c92a5ebdba0405c96e39d3a42 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Mar 2023 06:02:55 +0000 Subject: [PATCH 28/32] chore(deps): update actions/checkout action to v3.5.0 --- .github/workflows/create_github_release.yml | 2 +- .github/workflows/maven_tests.yml | 4 ++-- .github/workflows/prepare_release_changelog.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create_github_release.yml b/.github/workflows/create_github_release.yml index 3ae9aacea5..f9969d9627 100644 --- a/.github/workflows/create_github_release.yml +++ b/.github/workflows/create_github_release.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3.4.0 + uses: actions/checkout@v3.5.0 - name: Create Release id: create_release diff --git a/.github/workflows/maven_tests.yml b/.github/workflows/maven_tests.yml index d5f64403f8..a2926e5868 100644 --- a/.github/workflows/maven_tests.yml +++ b/.github/workflows/maven_tests.yml @@ -45,7 +45,7 @@ jobs: steps: ## Checkout the current version of the code from the repo. - name: Checkout latest code - uses: actions/checkout@v3.4.0 + uses: actions/checkout@v3.5.0 with: fetch-depth: "0" @@ -109,7 +109,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout latest code - uses: actions/checkout@v3.4.0 + uses: actions/checkout@v3.5.0 with: fetch-depth: "0" - name: Set up JDK 11 diff --git a/.github/workflows/prepare_release_changelog.yml b/.github/workflows/prepare_release_changelog.yml index 2cd862313a..2c6c175b99 100644 --- a/.github/workflows/prepare_release_changelog.yml +++ b/.github/workflows/prepare_release_changelog.yml @@ -15,7 +15,7 @@ jobs: # Check out current repository - name: Fetch Sources - uses: actions/checkout@v3.4.0 + uses: actions/checkout@v3.5.0 # Setup Java 11 environment for the next steps - name: Setup Java From bba8a994aa26020128a254e521ca7150a22e346b Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Fri, 31 Mar 2023 08:20:02 +0200 Subject: [PATCH 29/32] Update changelog --- changelog.md | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index 1d2e3c1876..0ceed0ca2f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,7 +1,7 @@ -Next Release (Version 3.25.2-snapshot) ------------------- -[issues resolved](https://github.com/javaparser/javaparser/milestone/198?closed=1) +Next Release (Version 3.25.3-snapshot) +-------------------------------------- +[issues resolved](https://github.com/javaparser/javaparser/milestone/199?closed=1) ### Added ### Changed @@ -10,6 +10,37 @@ Next Release (Version 3.25.2-snapshot) ### Fixed ### Security +Version 3.25.2 +-------------- +[issues resolved](https://github.com/javaparser/javaparser/milestone/198?closed=1) + +### Changed + +* chore(deps): bump maven-scm-plugin from 1.13.0 to 2.0.0 (PR [#3961](https://github.com/javaparser/javaparser/pull/3961) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump checkstyle from 10.8.1 to 10.9.1 (PR [#3958](https://github.com/javaparser/javaparser/pull/3958) by [@dependabot[bot]](https://github.com/apps/dependabot)) +* chore(deps): bump actions/checkout from 3.3.0 to 3.4.0 (PR [#3954](https://github.com/javaparser/javaparser/pull/3954) by [@dependabot[bot]](https://github.com/apps/dependabot)) + +### Fixed + +* Fix: issue 3947 MANIFEST.MF points to non-existent URL (PR [#3966](https://github.com/javaparser/javaparser/pull/3966) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue 3951 ConfilictingGenericTypesException is thrown when an Object type is expected as a parameter and an interface is provided as the actual parameter (PR [#3963](https://github.com/javaparser/javaparser/pull/3963) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue 3949 LexicalPreservingPrinter Ignores Changes to LambdaExp… (PR [#3959](https://github.com/javaparser/javaparser/pull/3959) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: Unit test since Return-Type-Substituable is fully implemented on reference type (PR [#3943](https://github.com/javaparser/javaparser/pull/3943) by [@jlerbsc](https://github.com/jlerbsc)) +* Fix: issue on FunctionalInterfaceLogic but waiting for Return-Type-Su… (PR [#3941](https://github.com/javaparser/javaparser/pull/3941) by [@jlerbsc](https://github.com/jlerbsc)) +* Suggested fix: hardcoded specific LambdaExpr case in LexicalDifferenc… (PR [#3938](https://github.com/javaparser/javaparser/pull/3938) by [@blacelle](https://github.com/blacelle)) +* Fix TextBlockLiteralExpr in LexicalDifferenceCalculator (PR [#3937](https://github.com/javaparser/javaparser/pull/3937) by [@blacelle](https://github.com/blacelle)) +* Fix: issue 3919 An array of primitive type cannot be assigned to an array of object (PR [#3933](https://github.com/javaparser/javaparser/pull/3933) by [@jlerbsc](https://github.com/jlerbsc)) + +### Developer Changes + +* chore(deps): update actions/checkout action to v3.5.0 (PR [#3953](https://github.com/javaparser/javaparser/pull/3953) by [@renovate[bot]](https://github.com/apps/renovate)) + +### :heart: Contributors + +Thank You to all contributors who worked on this release! + +* [@blacelle](https://github.com/blacelle) +* [@jlerbsc](https://github.com/jlerbsc) Version 3.25.1 From 99af3b86dfaa931df7bf2f540b686f566866b68b Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Fri, 31 Mar 2023 08:21:15 +0200 Subject: [PATCH 30/32] update readme --- readme.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index 0352c5dd5e..bafbd5717c 100644 --- a/readme.md +++ b/readme.md @@ -37,14 +37,14 @@ Just add the following to your maven configuration or tailor to your own depende com.github.javaparser javaparser-symbol-solver-core - 3.25.1 + 3.25.2 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.25.1' +implementation 'com.github.javaparser:javaparser-symbol-solver-core:3.25.2' ``` Since Version 3.5.10, the JavaParser project includes the JavaSymbolSolver. @@ -59,14 +59,14 @@ Using the dependency above will add both JavaParser and JavaSymbolSolver to your com.github.javaparser javaparser-core - 3.25.1 + 3.25.2 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-core:3.25.1' +implementation 'com.github.javaparser:javaparser-core:3.25.2' ``` Since version 3.6.17 the AST can be serialized to JSON. @@ -78,14 +78,14 @@ There is a separate module for this: com.github.javaparser javaparser-core-serialization - 3.25.1 + 3.25.2 ``` **Gradle**: ``` -implementation 'com.github.javaparser:javaparser-core-serialization:3.25.1' +implementation 'com.github.javaparser:javaparser-core-serialization:3.25.2' ``` ## How To Compile Sources From 6b9ff217c2f3bedabc7dd51c67011653defa6152 Mon Sep 17 00:00:00 2001 From: jlerbsc Date: Fri, 31 Mar 2023 08:23:12 +0200 Subject: [PATCH 31/32] [maven-release-plugin] prepare release javaparser-parent-3.25.2 --- javaparser-core-generators/pom.xml | 2 +- javaparser-core-metamodel-generator/pom.xml | 2 +- javaparser-core-serialization/pom.xml | 2 +- javaparser-core-testing-bdd/pom.xml | 2 +- javaparser-core-testing/pom.xml | 2 +- javaparser-core/pom.xml | 2 +- javaparser-symbol-solver-core/pom.xml | 2 +- javaparser-symbol-solver-testing/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/javaparser-core-generators/pom.xml b/javaparser-core-generators/pom.xml index 33fc2aaf44..44363b7592 100644 --- a/javaparser-core-generators/pom.xml +++ b/javaparser-core-generators/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-core-metamodel-generator/pom.xml b/javaparser-core-metamodel-generator/pom.xml index 6a65bbd868..529079cceb 100644 --- a/javaparser-core-metamodel-generator/pom.xml +++ b/javaparser-core-metamodel-generator/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-core-serialization/pom.xml b/javaparser-core-serialization/pom.xml index 43456b3ee2..95cd7fc419 100644 --- a/javaparser-core-serialization/pom.xml +++ b/javaparser-core-serialization/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-core-testing-bdd/pom.xml b/javaparser-core-testing-bdd/pom.xml index 7f5637519a..10ceab2ab0 100644 --- a/javaparser-core-testing-bdd/pom.xml +++ b/javaparser-core-testing-bdd/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-core-testing/pom.xml b/javaparser-core-testing/pom.xml index 820b0cf3c7..d63c10e2cf 100644 --- a/javaparser-core-testing/pom.xml +++ b/javaparser-core-testing/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-core/pom.xml b/javaparser-core/pom.xml index 7b5b43662a..0a8eb9cc0a 100644 --- a/javaparser-core/pom.xml +++ b/javaparser-core/pom.xml @@ -2,7 +2,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-symbol-solver-core/pom.xml b/javaparser-symbol-solver-core/pom.xml index 2260ff511c..01b0776571 100644 --- a/javaparser-symbol-solver-core/pom.xml +++ b/javaparser-symbol-solver-core/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/javaparser-symbol-solver-testing/pom.xml b/javaparser-symbol-solver-testing/pom.xml index e201e0504d..5ba6e1fbdf 100644 --- a/javaparser-symbol-solver-testing/pom.xml +++ b/javaparser-symbol-solver-testing/pom.xml @@ -3,7 +3,7 @@ javaparser-parent com.github.javaparser - 3.25.2-SNAPSHOT + 3.25.2 4.0.0 diff --git a/pom.xml b/pom.xml index 5dfa4a0757..68cd79ce0f 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ com.github.javaparser javaparser-parent pom - 3.25.2-SNAPSHOT + 3.25.2 javaparser-parent https://github.com/javaparser From 93f20d6bc79674e83ae7e203509534d9051ea423 Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Fri, 31 Mar 2023 08:12:06 -0700 Subject: [PATCH 32/32] Update stubparser version. --- .../com/github/javaparser/utils/Bla.java | 4 +- .../github/javaparser/utils/module-info.java | 4 +- .../issue2615/with_module_info/demo/Main.java | 92 +++++++++---------- .../with_module_info/demo/module-info.java | 4 +- .../with_module_info_in_root/demo/Main.java | 92 +++++++++---------- .../with_module_info_in_root/module-info.java | 4 +- .../without_module_info/demo/Main.java | 92 +++++++++---------- javaparser-core/pom.xml | 2 +- 8 files changed, 147 insertions(+), 147 deletions(-) diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java index a81184b5c1..eeeb6f19e7 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/Bla.java @@ -1,2 +1,2 @@ -class X { -} +class X { +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java index 119be4ee19..a4a0ddbf86 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/module-info.java @@ -1,2 +1,2 @@ -module M.N { -} +module M.N { +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/Main.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/Main.java index c8db09696b..60dca7d294 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/Main.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/Main.java @@ -1,46 +1,46 @@ -package demo; - -import com.github.javaparser.ParseResult; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.utils.ParserCollectionStrategy; -import com.github.javaparser.utils.ProjectRoot; -import com.github.javaparser.utils.SourceRoot; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ -public class Main { - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("Usage: provide one or more directory names to process"); - System.exit(1); - } - for (String dir : args) { - process(dir); - } - } - - private static void process(String dir) { - Path root = Paths.get(dir); - Callback cb = new Callback(); - ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); - projectRoot.getSourceRoots().forEach(sourceRoot -> { - try { - sourceRoot.parse("", cb); - } catch (IOException e) { - System.err.println("IOException: " + e); - } - }); - } - - private static class Callback implements SourceRoot.Callback { - - @Override - public Result process(Path localPath, Path absolutePath, ParseResult result) { - System.out.printf("Found %s%n", absolutePath); - return Result.SAVE; - } - } -} +package demo; + +import com.github.javaparser.ParseResult; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.utils.ParserCollectionStrategy; +import com.github.javaparser.utils.ProjectRoot; +import com.github.javaparser.utils.SourceRoot; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ +public class Main { + + public static void main(String[] args) { + if (args.length < 1) { + System.err.println("Usage: provide one or more directory names to process"); + System.exit(1); + } + for (String dir : args) { + process(dir); + } + } + + private static void process(String dir) { + Path root = Paths.get(dir); + Callback cb = new Callback(); + ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); + projectRoot.getSourceRoots().forEach(sourceRoot -> { + try { + sourceRoot.parse("", cb); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + }); + } + + private static class Callback implements SourceRoot.Callback { + + @Override + public Result process(Path localPath, Path absolutePath, ParseResult result) { + System.out.printf("Found %s%n", absolutePath); + return Result.SAVE; + } + } +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/module-info.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/module-info.java index abd7417e79..38c78e1d38 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/module-info.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info/demo/module-info.java @@ -1,2 +1,2 @@ -module demo { -} +module demo { +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/demo/Main.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/demo/Main.java index c8db09696b..60dca7d294 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/demo/Main.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/demo/Main.java @@ -1,46 +1,46 @@ -package demo; - -import com.github.javaparser.ParseResult; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.utils.ParserCollectionStrategy; -import com.github.javaparser.utils.ProjectRoot; -import com.github.javaparser.utils.SourceRoot; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ -public class Main { - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("Usage: provide one or more directory names to process"); - System.exit(1); - } - for (String dir : args) { - process(dir); - } - } - - private static void process(String dir) { - Path root = Paths.get(dir); - Callback cb = new Callback(); - ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); - projectRoot.getSourceRoots().forEach(sourceRoot -> { - try { - sourceRoot.parse("", cb); - } catch (IOException e) { - System.err.println("IOException: " + e); - } - }); - } - - private static class Callback implements SourceRoot.Callback { - - @Override - public Result process(Path localPath, Path absolutePath, ParseResult result) { - System.out.printf("Found %s%n", absolutePath); - return Result.SAVE; - } - } -} +package demo; + +import com.github.javaparser.ParseResult; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.utils.ParserCollectionStrategy; +import com.github.javaparser.utils.ProjectRoot; +import com.github.javaparser.utils.SourceRoot; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ +public class Main { + + public static void main(String[] args) { + if (args.length < 1) { + System.err.println("Usage: provide one or more directory names to process"); + System.exit(1); + } + for (String dir : args) { + process(dir); + } + } + + private static void process(String dir) { + Path root = Paths.get(dir); + Callback cb = new Callback(); + ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); + projectRoot.getSourceRoots().forEach(sourceRoot -> { + try { + sourceRoot.parse("", cb); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + }); + } + + private static class Callback implements SourceRoot.Callback { + + @Override + public Result process(Path localPath, Path absolutePath, ParseResult result) { + System.out.printf("Found %s%n", absolutePath); + return Result.SAVE; + } + } +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/module-info.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/module-info.java index abd7417e79..38c78e1d38 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/module-info.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/with_module_info_in_root/module-info.java @@ -1,2 +1,2 @@ -module demo { -} +module demo { +} diff --git a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/without_module_info/demo/Main.java b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/without_module_info/demo/Main.java index c8db09696b..60dca7d294 100644 --- a/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/without_module_info/demo/Main.java +++ b/javaparser-core-testing/src/test/resources/com/github/javaparser/utils/projectroot/issue2615/without_module_info/demo/Main.java @@ -1,46 +1,46 @@ -package demo; - -import com.github.javaparser.ParseResult; -import com.github.javaparser.ast.CompilationUnit; -import com.github.javaparser.utils.ParserCollectionStrategy; -import com.github.javaparser.utils.ProjectRoot; -import com.github.javaparser.utils.SourceRoot; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ -public class Main { - - public static void main(String[] args) { - if (args.length < 1) { - System.err.println("Usage: provide one or more directory names to process"); - System.exit(1); - } - for (String dir : args) { - process(dir); - } - } - - private static void process(String dir) { - Path root = Paths.get(dir); - Callback cb = new Callback(); - ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); - projectRoot.getSourceRoots().forEach(sourceRoot -> { - try { - sourceRoot.parse("", cb); - } catch (IOException e) { - System.err.println("IOException: " + e); - } - }); - } - - private static class Callback implements SourceRoot.Callback { - - @Override - public Result process(Path localPath, Path absolutePath, ParseResult result) { - System.out.printf("Found %s%n", absolutePath); - return Result.SAVE; - } - } -} +package demo; + +import com.github.javaparser.ParseResult; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.utils.ParserCollectionStrategy; +import com.github.javaparser.utils.ProjectRoot; +import com.github.javaparser.utils.SourceRoot; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* If there is a module declaration in the root directory, JavaParser doesn't find any .java files. */ +public class Main { + + public static void main(String[] args) { + if (args.length < 1) { + System.err.println("Usage: provide one or more directory names to process"); + System.exit(1); + } + for (String dir : args) { + process(dir); + } + } + + private static void process(String dir) { + Path root = Paths.get(dir); + Callback cb = new Callback(); + ProjectRoot projectRoot = new ParserCollectionStrategy().collect(root); + projectRoot.getSourceRoots().forEach(sourceRoot -> { + try { + sourceRoot.parse("", cb); + } catch (IOException e) { + System.err.println("IOException: " + e); + } + }); + } + + private static class Callback implements SourceRoot.Callback { + + @Override + public Result process(Path localPath, Path absolutePath, ParseResult result) { + System.out.printf("Found %s%n", absolutePath); + return Result.SAVE; + } + } +} diff --git a/javaparser-core/pom.xml b/javaparser-core/pom.xml index a6d2212cd0..754c667b46 100644 --- a/javaparser-core/pom.xml +++ b/javaparser-core/pom.xml @@ -30,7 +30,7 @@ - stubparser-3.25.1 + stubparser-3.25.2 com.helger.maven