From 904fb1e7001a8b686c6956e32c4cc0cdb6e2f80b Mon Sep 17 00:00:00 2001 From: MartinWitt Date: Mon, 2 Mar 2020 08:33:24 +0100 Subject: [PATCH] fix: NullPointerException on CtTypeReferenceImpl.isGenerics (#3276) --- .../CtTypeParameterReferenceImpl.java | 2 +- src/test/java/spoon/Issue3275Test.java | 25 ++++++ .../resources/issue3275/BOMCostPrice.java | 77 +++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/test/java/spoon/Issue3275Test.java create mode 100644 src/test/resources/issue3275/BOMCostPrice.java diff --git a/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java b/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java index 9fd2828c0c0..5e74ba1b28c 100644 --- a/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java +++ b/src/main/java/spoon/support/reflect/reference/CtTypeParameterReferenceImpl.java @@ -128,7 +128,7 @@ public CtTypeParameter getDeclaration() { if (parent instanceof CtExecutableReference) { CtExecutableReference parentExec = (CtExecutableReference) parent; - if (!parentExec.getDeclaringType().equals(e)) { + if (Objects.nonNull(parentExec.getDeclaringType()) && !parentExec.getDeclaringType().equals(e)) { CtElement parent2 = parentExec.getExecutableDeclaration(); if (parent2 instanceof CtMethod) { e = parent2; diff --git a/src/test/java/spoon/Issue3275Test.java b/src/test/java/spoon/Issue3275Test.java new file mode 100644 index 00000000000..205322684b5 --- /dev/null +++ b/src/test/java/spoon/Issue3275Test.java @@ -0,0 +1,25 @@ +package spoon; + +import org.junit.Test; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.CtModel; +import spoon.reflect.reference.CtTypeReference; + +/** + * Issue3275 + */ +public class Issue3275Test { + // the following code reproduces the behavior from the issue + @Test + public void test() { + CtModel model = new FluentLauncher().inputResource("src/test/resources/issue3275/BOMCostPrice.java") + .noClasspath(true) + .processor(new AbstractProcessor>() { + public void process(CtTypeReference element) { + System.out.println(element.isGenerics()); + } + }) + .buildModel(); + } +} diff --git a/src/test/resources/issue3275/BOMCostPrice.java b/src/test/resources/issue3275/BOMCostPrice.java new file mode 100644 index 00000000000..25d320b7f63 --- /dev/null +++ b/src/test/resources/issue3275/BOMCostPrice.java @@ -0,0 +1,77 @@ +package org.eevolution.costing; + +import java.util.Collection; +import java.util.HashMap; +import java.util.stream.Stream; + +import com.google.common.base.Predicates; + +import de.metas.costing.CostAmount; +import de.metas.costing.CostElementId; +import de.metas.product.ProductId; +import de.metas.util.GuavaCollectors; +import de.metas.util.lang.RepoIdAware; +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.Singular; +import lombok.ToString; + +@ToString +public class BOMCostPrice { + public static BOMCostPrice empty(@NonNull final ProductId productId) { + return builder().productId(productId).build(); + } + + @Getter + private final ProductId productId; + private final HashMap pricesByElementId; + + @Builder + private BOMCostPrice(@NonNull final ProductId productId, + @NonNull @Singular final Collection costElementPrices) { + this.productId = productId; + pricesByElementId = costElementPrices.stream() + .collect(GuavaCollectors.toHashMapByKey(BOMCostElementPrice::getCostElementId)); + } + + public Stream streamCostElementIds() { + return pricesByElementId.keySet().stream(); + } + + public BOMCostElementPrice getCostElementPriceOrNull(@NonNull final CostElementId costElementId) { + return pricesByElementId.get(costElementId); + } + + public void clearOwnCostPrice(@NonNull final CostElementId costElementId) { + final BOMCostElementPrice elementCostPrice = getCostElementPriceOrNull(costElementId); + if (elementCostPrice != null) { + elementCostPrice.clearOwnCostPrice(); + } + } + + public void setComponentsCostPrice(@NonNull final CostAmount costPrice, + @NonNull final CostElementId costElementId) { + pricesByElementId + .computeIfAbsent(costElementId, k -> BOMCostElementPrice.zero(costElementId, costPrice.getCurrencyId())) + .setComponentsCostPrice(costPrice); + } + + public void clearComponentsCostPrice(@NonNull final CostElementId costElementId) { + final BOMCostElementPrice elementCostPrice = getCostElementPriceOrNull(costElementId); + if (elementCostPrice != null) { + elementCostPrice.clearComponentsCostPrice(); + } + } + + Collection getElementPrices() { + return pricesByElementId.values(); + } + + Stream streamIds(@NonNull final Class idType) { + return getElementPrices().stream() + .map(BOMCostElementPrice::getId) + .filter(Predicates.notNull()) + .map(idType::cast); + } +}