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 d7db6796..0a92d558 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().get(0))); + return Optional.of(new AddInvocation(collection, executableReference, ctInvocation.getArguments().getFirst())); } } @@ -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.get(0)), + ExpressionUtil.getExpressionType(values.getFirst()), 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 27e74d7c..7be14144 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,11 +42,7 @@ private void checkComments(Collection comments) { } private static boolean isStandaloneComment(CtComment ctComment) { - var parent = ctComment.getParent(); - if (parent == null) { - return false; - } - return !parent.getComments().contains(ctComment); + return ctComment.getParent() instanceof CtElement ctElement && !ctElement.getComments().contains(ctComment); } @Override @@ -75,7 +71,7 @@ public void process(CtElement element) { .map(CtComment.class::cast) .collect(Collectors.toCollection(ArrayList::new)); - followingComments.add(0, ctComment); + followingComments.addFirst(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 c23265df..8f748cda 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 @@ -241,9 +241,7 @@ private static List> findPreviousAssignee(CtVariableRead ctVa boolean foundPreviousAssignment = false; CtStatement currentStatement = ctVariableRead.getParent(CtStatement.class); - var reversedStatements = new ArrayList<>(StatementUtil.getEffectiveStatements(ctExecutable.getBody())); - Collections.reverse(reversedStatements); - for (CtStatement ctStatement : reversedStatements) { + for (CtStatement ctStatement : StatementUtil.getEffectiveStatements(ctExecutable.getBody()).reversed()) { if (!foundPreviousAssignment) { if (ctStatement == currentStatement) { foundPreviousAssignment = true; @@ -282,7 +280,7 @@ && isParameterOf(ctVariableDeclaration, ctExecutable)) { List> previousAssignees = findPreviousAssignee(ctVariableRead); if (!previousAssignees.isEmpty()) { - return findParameterReference(previousAssignees.get(0), ctExecutable); + return findParameterReference(previousAssignees.getFirst(), ctExecutable); } return Option.some((CtParameter) ctVariableDeclaration); @@ -445,11 +443,13 @@ private void checkCtType(CtType ctType) { ctTypeMember = fixRecordAccessor(ctRecord, ctMethod); } - if (ctTypeMember instanceof CtConstructor ctConstructor) { - checkCtExecutableAssign(ctConstructor); - } else if (ctTypeMember instanceof CtMethod ctMethod) { - checkCtExecutableReturn(ctMethod); - checkCtExecutableAssign(ctMethod); + switch (ctTypeMember) { + case CtConstructor ctConstructor -> checkCtExecutableAssign(ctConstructor); + case CtMethod ctMethod -> { + checkCtExecutableReturn(ctMethod); + checkCtExecutableAssign(ctMethod); + } + default -> {} } } } 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 ba0598cf..edb044bc 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 someValue) { - return new Some<>(function.apply(someValue.value)); + if (this instanceof Some(T value)) { + return new Some<>(function.apply(value)); } else if (this instanceof None) { return new None<>(); } @@ -56,8 +56,8 @@ default T nullable() { } default Stream stream() { - if (this instanceof Some someValue) { - return Stream.of(someValue.value); + if (this instanceof Some(T value)) { + return Stream.of(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 ef3784ee..bda24efa 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,7 +10,6 @@ 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; @@ -20,8 +19,6 @@ 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 56557f0d..3129d3ad 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,6 +137,10 @@ 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 3be22dbb..32a83697 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,6 +38,7 @@ 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; @@ -78,16 +79,13 @@ private static UsesFinder getFor(FactoryAccessor factoryAccessor) { */ @SuppressWarnings("rawtypes") public static CtElementStream getAllUses(CtNamedElement element) { - 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()); + 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()); + }; } public static CtElementStream> variableUses(CtVariable variable) { @@ -183,7 +181,10 @@ public static boolean isAccessingVariable(CtVariable ctVariable, CtVariableAc } public static CtVariable getDeclaredVariable(CtVariableAccess ctVariableAccess) { - return UsesFinder.getFor(ctVariableAccess).scanner.variableAccessDeclarations.getOrDefault(ctVariableAccess, null); + return UsesFinder.getFor(ctVariableAccess).scanner.variableAccessDeclarations.getOrDefault( + ctVariableAccess, + VariableUtil.getVariableDeclaration(ctVariableAccess.getVariable()) + ); } /** * The scanner searches for uses of supported code elements in a single pass over the entire model. @@ -198,7 +199,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 3d066483..4d8dc244 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 otherStructuralElement)) { + if (!(otherObject instanceof StructuralElement(var otherElement))) { return false; } - return StructuralEqualsVisitor.equals(this.element, otherStructuralElement.element); + return StructuralEqualsVisitor.equals(this.element, otherElement); } @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 f57f65d3..9de6e57a 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,6 +15,7 @@ import spoon.support.visitor.equals.EqualsVisitor; import java.util.LinkedHashSet; +import java.util.SequencedSet; import java.util.Set; public final class StructuralEqualsVisitor extends EqualsVisitor { @@ -25,7 +26,7 @@ public final class StructuralEqualsVisitor extends EqualsVisitor { CtRole.COMMENT, CtRole.COMMENT_CONTENT, CtRole.COMMENT_TAG, CtRole.COMMENT_TYPE ); - private final Set differences; + private final SequencedSet differences; public record Difference(CtRole role, Object left, Object right) {} @@ -117,7 +118,7 @@ protected boolean fail(CtRole role, Object element, Object other) { * * @return the differences */ - public Set differences() { + public SequencedSet differences() { return new LinkedHashSet<>(this.differences); } } diff --git a/pom.xml b/pom.xml index 72fa78be..b82893b4 100644 --- a/pom.xml +++ b/pom.xml @@ -38,7 +38,7 @@ UTF-8 - 17 + 21 ${java.version} ${java.version} ${java.version}