diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/check/api/SequentialAddAll.java b/autograder-core/src/main/java/de/firemage/autograder/core/check/api/SequentialAddAll.java index 0a92d558..d7db6796 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/check/api/SequentialAddAll.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/check/api/SequentialAddAll.java @@ -62,7 +62,7 @@ static Optional of(CtStatement ctStatement) { return Optional.empty(); } - return Optional.of(new AddInvocation(collection, executableReference, ctInvocation.getArguments().getFirst())); + return Optional.of(new AddInvocation(collection, executableReference, ctInvocation.getArguments().get(0))); } } @@ -91,7 +91,7 @@ private void reportProblem(CtVariableReference ctVariable, List ctVariable, List SOME_GOOD_NAME = List.of(%s); /* ... */ %s.addAll(SOME_GOOD_NAME)".formatted( - ExpressionUtil.getExpressionType(values.getFirst()), + ExpressionUtil.getExpressionType(values.get(0)), values.stream() .map(CtElement::toString) .collect(Collectors.joining(", ")), diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/check/comment/UnnecessaryComment.java b/autograder-core/src/main/java/de/firemage/autograder/core/check/comment/UnnecessaryComment.java index 7be14144..27e74d7c 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/check/comment/UnnecessaryComment.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/check/comment/UnnecessaryComment.java @@ -42,7 +42,11 @@ private void checkComments(Collection comments) { } private static boolean isStandaloneComment(CtComment ctComment) { - return ctComment.getParent() instanceof CtElement ctElement && !ctElement.getComments().contains(ctComment); + var parent = ctComment.getParent(); + if (parent == null) { + return false; + } + return !parent.getComments().contains(ctComment); } @Override @@ -71,7 +75,7 @@ public void process(CtElement element) { .map(CtComment.class::cast) .collect(Collectors.toCollection(ArrayList::new)); - followingComments.addFirst(ctComment); + followingComments.add(0, ctComment); checkComments(followingComments); return; diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/check/oop/LeakedCollectionCheck.java b/autograder-core/src/main/java/de/firemage/autograder/core/check/oop/LeakedCollectionCheck.java index 127cb835..8ca12338 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/check/oop/LeakedCollectionCheck.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/check/oop/LeakedCollectionCheck.java @@ -37,6 +37,7 @@ import spoon.reflect.declaration.CtTypeMember; import spoon.reflect.declaration.CtTypedElement; import spoon.reflect.declaration.CtVariable; +import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.filter.TypeFilter; @@ -240,7 +241,9 @@ private static List> findPreviousAssignee(CtVariableRead ctVa boolean foundPreviousAssignment = false; CtStatement currentStatement = ctVariableRead.getParent(CtStatement.class); - for (CtStatement ctStatement : StatementUtil.getEffectiveStatements(ctExecutable.getBody()).reversed()) { + var reversedStatements = new ArrayList<>(StatementUtil.getEffectiveStatements(ctExecutable.getBody())); + Collections.reverse(reversedStatements); + for (CtStatement ctStatement : reversedStatements) { if (!foundPreviousAssignment) { if (ctStatement == currentStatement) { foundPreviousAssignment = true; @@ -279,7 +282,7 @@ && isParameterOf(ctVariableDeclaration, ctExecutable)) { List> previousAssignees = findPreviousAssignee(ctVariableRead); if (!previousAssignees.isEmpty()) { - return findParameterReference(previousAssignees.getFirst(), ctExecutable); + return findParameterReference(previousAssignees.get(0), ctExecutable); } return Option.some((CtParameter) ctVariableDeclaration); @@ -420,13 +423,11 @@ private void checkCtType(CtType ctType) { } for (CtTypeMember ctTypeMember : ctType.getTypeMembers()) { - switch (ctTypeMember) { - case CtConstructor ctConstructor -> checkCtExecutableAssign(ctConstructor); - case CtMethod ctMethod -> { - checkCtExecutableReturn(ctMethod); - checkCtExecutableAssign(ctMethod); - } - default -> {} + if (ctTypeMember instanceof CtConstructor ctConstructor) { + checkCtExecutableAssign(ctConstructor); + } else if (ctTypeMember instanceof CtMethod ctMethod) { + checkCtExecutableReturn(ctMethod); + checkCtExecutableAssign(ctMethod); } } } diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/check/utils/Option.java b/autograder-core/src/main/java/de/firemage/autograder/core/check/utils/Option.java index edb044bc..ba0598cf 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/check/utils/Option.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/check/utils/Option.java @@ -33,8 +33,8 @@ default boolean isSome() { } default Option map(Function function) { - if (this instanceof Some(T value)) { - return new Some<>(function.apply(value)); + if (this instanceof Some someValue) { + return new Some<>(function.apply(someValue.value)); } else if (this instanceof None) { return new None<>(); } @@ -56,8 +56,8 @@ default T nullable() { } default Stream stream() { - if (this instanceof Some(T value)) { - return Stream.of(value); + if (this instanceof Some someValue) { + return Stream.of(someValue.value); } else if (this instanceof None) { return Stream.empty(); } diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/ExpressionUtil.java b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/ExpressionUtil.java index bda24efa..ef3784ee 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/ExpressionUtil.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/ExpressionUtil.java @@ -10,6 +10,7 @@ import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtConditional; import spoon.reflect.code.CtExpression; +import spoon.reflect.code.CtFieldRead; import spoon.reflect.code.CtInvocation; import spoon.reflect.code.CtLiteral; import spoon.reflect.code.CtTextBlock; @@ -19,6 +20,8 @@ import spoon.reflect.code.LiteralBase; import spoon.reflect.code.UnaryOperatorKind; import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtEnum; +import spoon.reflect.declaration.CtEnumValue; import spoon.reflect.declaration.CtTypedElement; import spoon.reflect.declaration.CtVariable; import spoon.reflect.eval.PartialEvaluator; diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/TypeUtil.java b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/TypeUtil.java index 3129d3ad..56557f0d 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/TypeUtil.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/TypeUtil.java @@ -137,10 +137,6 @@ public static boolean isTypeEqualTo(CtTypeReference ctType, CtTypeReference ctTypeReference, Class expected) { CtType expectedType = ctTypeReference.getFactory().Type().get(expected); - return isSubtypeOf(ctTypeReference, expectedType); - } - - public static boolean isSubtypeOf(CtTypeReference ctTypeReference, CtType expectedType) { if (ctTypeReference.getTypeDeclaration() == null || ctTypeReference instanceof CtTypeParameterReference) { return ctTypeReference.isSubtypeOf(expectedType.getReference()); } diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/UsesFinder.java b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/UsesFinder.java index 32a83697..3be22dbb 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/UsesFinder.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/UsesFinder.java @@ -38,7 +38,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.SequencedSet; import java.util.Set; import java.util.stream.Stream; @@ -79,13 +78,16 @@ private static UsesFinder getFor(FactoryAccessor factoryAccessor) { */ @SuppressWarnings("rawtypes") public static CtElementStream getAllUses(CtNamedElement element) { - return switch (element) { - case CtVariable variable -> UsesFinder.variableUses(variable).asUntypedStream(); - case CtTypeParameter typeParameter -> UsesFinder.typeParameterUses(typeParameter).asUntypedStream(); - case CtExecutable executable -> UsesFinder.executableUses(executable).asUntypedStream(); - case CtType type -> UsesFinder.typeUses(type).asUntypedStream(); - default -> throw new IllegalArgumentException("Unsupported element: " + element.getClass().getName()); - }; + if (element instanceof CtVariable variable) { + return UsesFinder.variableUses(variable).asUntypedStream(); + } else if (element instanceof CtTypeParameter typeParameter) { + return UsesFinder.typeParameterUses(typeParameter).asUntypedStream(); + } else if (element instanceof CtExecutable executable) { + return UsesFinder.executableUses(executable).asUntypedStream(); + } else if (element instanceof CtType type) { + return UsesFinder.typeUses(type).asUntypedStream(); + } + throw new IllegalArgumentException("Unsupported element: " + element.getClass().getName()); } public static CtElementStream> variableUses(CtVariable variable) { @@ -181,10 +183,7 @@ public static boolean isAccessingVariable(CtVariable ctVariable, CtVariableAc } public static CtVariable getDeclaredVariable(CtVariableAccess ctVariableAccess) { - return UsesFinder.getFor(ctVariableAccess).scanner.variableAccessDeclarations.getOrDefault( - ctVariableAccess, - VariableUtil.getVariableDeclaration(ctVariableAccess.getVariable()) - ); + return UsesFinder.getFor(ctVariableAccess).scanner.variableAccessDeclarations.getOrDefault(ctVariableAccess, null); } /** * The scanner searches for uses of supported code elements in a single pass over the entire model. @@ -199,7 +198,7 @@ private static class UsesScanner extends CtScanner { private final Map> typeParameterUses = new IdentityHashMap<>(); private final Map> executableUses = new IdentityHashMap<>(); private final Map> typeUses = new IdentityHashMap<>(); - private final Map> subtypes = new IdentityHashMap<>(); + private final Map> subtypes = new IdentityHashMap<>(); // Caches the current instanceof pattern variables, since Spoon doesn't track them yet // We are conservative: A pattern introduces a variable until the end of the current block diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralElement.java b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralElement.java index 4d8dc244..3d066483 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralElement.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralElement.java @@ -12,11 +12,11 @@ public boolean equals(Object otherObject) { if (this == otherObject) { return true; } - if (!(otherObject instanceof StructuralElement(var otherElement))) { + if (!(otherObject instanceof StructuralElement otherStructuralElement)) { return false; } - return StructuralEqualsVisitor.equals(this.element, otherElement); + return StructuralEqualsVisitor.equals(this.element, otherStructuralElement.element); } @Override diff --git a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralEqualsVisitor.java b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralEqualsVisitor.java index 9de6e57a..f57f65d3 100644 --- a/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralEqualsVisitor.java +++ b/autograder-core/src/main/java/de/firemage/autograder/core/integrated/structure/StructuralEqualsVisitor.java @@ -15,7 +15,6 @@ import spoon.support.visitor.equals.EqualsVisitor; import java.util.LinkedHashSet; -import java.util.SequencedSet; import java.util.Set; public final class StructuralEqualsVisitor extends EqualsVisitor { @@ -26,7 +25,7 @@ public final class StructuralEqualsVisitor extends EqualsVisitor { CtRole.COMMENT, CtRole.COMMENT_CONTENT, CtRole.COMMENT_TAG, CtRole.COMMENT_TYPE ); - private final SequencedSet differences; + private final Set differences; public record Difference(CtRole role, Object left, Object right) {} @@ -118,7 +117,7 @@ protected boolean fail(CtRole role, Object element, Object other) { * * @return the differences */ - public SequencedSet differences() { + public Set differences() { return new LinkedHashSet<>(this.differences); } } diff --git a/pom.xml b/pom.xml index 38b6134c..df7417d5 100644 --- a/pom.xml +++ b/pom.xml @@ -46,7 +46,7 @@ UTF-8 - 21 + 17 ${java.version} ${java.version} ${java.version}