From 21d01bf575f6db98e0a9eefcb3ee2918b482bc5e Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Sun, 25 Aug 2024 15:32:28 -0700 Subject: [PATCH] resolve and remove some of the suppressed warnings The code generator required changing how the context was passed around so that it was not nullable. Otherwise minor touchups and deletion of suppressions that are not reproducable. --- .../cache/LocalCacheFactoryGenerator.java | 31 +-- .../caffeine/cache/NodeFactoryGenerator.java | 25 ++- .../caffeine/cache/local/AddConstructor.java | 10 +- .../caffeine/cache/local/AddDeques.java | 36 ++-- .../cache/local/AddExpirationTicker.java | 6 +- .../cache/local/AddExpireAfterAccess.java | 14 +- .../cache/local/AddExpireAfterWrite.java | 6 +- .../caffeine/cache/local/AddFastPath.java | 6 +- .../cache/local/AddKeyValueStrength.java | 21 +- .../caffeine/cache/local/AddMaximum.java | 46 ++--- .../caffeine/cache/local/AddPacer.java | 6 +- .../cache/local/AddRefreshAfterWrite.java | 6 +- .../cache/local/AddRemovalListener.java | 6 +- .../caffeine/cache/local/AddStats.java | 18 +- .../caffeine/cache/local/AddSubtype.java | 10 +- .../caffeine/cache/local/Finalize.java | 6 +- .../cache/local/LocalCacheContext.java | 20 +- .../caffeine/cache/local/LocalCacheRule.java | 21 +- .../caffeine/cache/node/AddConstructors.java | 63 +++--- .../caffeine/cache/node/AddDeques.java | 22 ++- .../caffeine/cache/node/AddExpiration.java | 81 ++++---- .../cache/node/AddFactoryMethods.java | 22 +-- .../caffeine/cache/node/AddHealth.java | 30 +-- .../benmanes/caffeine/cache/node/AddKey.java | 38 ++-- .../caffeine/cache/node/AddMaximum.java | 27 +-- .../caffeine/cache/node/AddSubtype.java | 15 +- .../caffeine/cache/node/AddValue.java | 53 +++--- .../caffeine/cache/node/Finalize.java | 10 +- .../caffeine/cache/node/NodeContext.java | 179 ++++++++++++++++-- .../caffeine/cache/node/NodeRule.java | 178 +---------------- .../caffeine/cache/impl/CoherenceCache.java | 12 +- .../caffeine/cache/AbstractLinkedDeque.java | 1 - .../caffeine/cache/BoundedLocalCache.java | 5 - .../caffeine/cache/UnboundedLocalCache.java | 4 - .../caffeine/cache/BoundedLocalCacheTest.java | 1 - .../cache/testing/GuavaCacheFromContext.java | 8 - gradle/config/pmd/rulesSets.xml | 6 - .../jcache/event/EventDispatcher.java | 1 - .../caffeine/cache/simulator/Simulate.java | 1 - .../policy/product/CoherencePolicy.java | 10 +- .../policy/product/ExpiringMapPolicy.java | 10 +- 41 files changed, 513 insertions(+), 558 deletions(-) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java index 149b56225d..b9b718a1d8 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/LocalCacheFactoryGenerator.java @@ -83,7 +83,6 @@ public final class LocalCacheFactoryGenerator { private final List factoryTypes; private final Path directory; - @SuppressWarnings("NullAway.Init") private LocalCacheFactoryGenerator(Path directory) { this.directory = requireNonNull(directory); this.factoryTypes = new ArrayList<>(); @@ -126,7 +125,7 @@ private void reformat() throws FormatterException, IOException { } private void generateLocalCaches() { - NavigableMap> classNameToFeatures = getClassNameToFeatures(); + NavigableMap> classNameToFeatures = getClassNameToFeatures(); classNameToFeatures.forEach((className, features) -> { String higherKey = classNameToFeatures.higherKey(className); boolean isLeaf = (higherKey == null) || !higherKey.startsWith(className); @@ -135,17 +134,17 @@ private void generateLocalCaches() { }); } - private NavigableMap> getClassNameToFeatures() { - var classNameToFeatures = new TreeMap>(); + private NavigableMap> getClassNameToFeatures() { + var classNameToFeatures = new TreeMap>(); for (List combination : combinations()) { - Set features = getFeatures(combination); + ImmutableSet features = getFeatures(combination); String className = encode(Feature.makeClassName(features)); classNameToFeatures.put(className, features); } return classNameToFeatures; } - private Set getFeatures(List combination) { + private ImmutableSet getFeatures(List combination) { var features = new LinkedHashSet(); features.add(((Boolean) combination.get(0)) ? Feature.STRONG_KEYS : Feature.WEAK_KEYS); features.add(((Boolean) combination.get(1)) ? Feature.STRONG_VALUES : Feature.INFIRM_VALUES); @@ -157,7 +156,7 @@ private Set getFeatures(List combination) { if (features.contains(Feature.MAXIMUM_WEIGHT)) { features.remove(Feature.MAXIMUM_SIZE); } - return features; + return ImmutableSet.copyOf(features); } private Set> combinations() { @@ -165,18 +164,18 @@ private Set> combinations() { return Sets.cartesianProduct(sets); } - @SuppressWarnings("NullAway") - private TypeSpec makeLocalCacheSpec(String className, boolean isFinal, Set features) { + private TypeSpec makeLocalCacheSpec(String className, + boolean isFinal, ImmutableSet features) { TypeName superClass; - Set parentFeatures; - Set generateFeatures; + ImmutableSet parentFeatures; + ImmutableSet generateFeatures; if (features.size() == 2) { - parentFeatures = Set.of(); + parentFeatures = ImmutableSet.of(); generateFeatures = features; superClass = BOUNDED_LOCAL_CACHE; } else { parentFeatures = ImmutableSet.copyOf(Iterables.limit(features, features.size() - 1)); - generateFeatures = ImmutableSet.of(Iterables.getLast(features)); + generateFeatures = ImmutableSet.of(features.asList().get(features.size() - 1)); superClass = ParameterizedTypeName.get(ClassName.bestGuess( encode(Feature.makeClassName(parentFeatures))), kTypeVar, vTypeVar); } @@ -184,9 +183,11 @@ private TypeSpec makeLocalCacheSpec(String className, boolean isFinal, Set rules = List.of(new AddSubtype(), new AddConstructors(), new AddKey(), new AddValue(), new AddMaximum(), new AddExpiration(), new AddDeques(), @@ -86,7 +85,6 @@ public final class NodeFactoryGenerator { private final List nodeTypes; private final Path directory; - @SuppressWarnings("NullAway.Init") private NodeFactoryGenerator(Path directory) { this.directory = requireNonNull(directory); this.nodeTypes = new ArrayList<>(); @@ -129,7 +127,7 @@ private void reformat() throws FormatterException, IOException { } private void generatedNodes() { - NavigableMap> classNameToFeatures = getClassNameToFeatures(); + NavigableMap> classNameToFeatures = getClassNameToFeatures(); classNameToFeatures.forEach((className, features) -> { String higherKey = classNameToFeatures.higherKey(className); boolean isLeaf = (higherKey == null) || !higherKey.startsWith(className); @@ -138,8 +136,8 @@ private void generatedNodes() { }); } - private NavigableMap> getClassNameToFeatures() { - var classNameToFeatures = new TreeMap>(); + private NavigableMap> getClassNameToFeatures() { + var classNameToFeatures = new TreeMap>(); for (List combination : combinations()) { var features = getFeatures(combination); var className = Feature.makeClassName(features); @@ -163,27 +161,28 @@ private ImmutableSet getFeatures(List combination) { return ImmutableSet.copyOf(features); } - @SuppressWarnings("NullAway") - private TypeSpec makeNodeSpec(String className, boolean isFinal, Set features) { + private TypeSpec makeNodeSpec(String className, boolean isFinal, ImmutableSet features) { TypeName superClass; - Set parentFeatures; - Set generateFeatures; + ImmutableSet parentFeatures; + ImmutableSet generateFeatures; if (features.size() == 2) { - parentFeatures = Set.of(); + parentFeatures = ImmutableSet.of(); generateFeatures = features; superClass = TypeName.OBJECT; } else { parentFeatures = ImmutableSet.copyOf(Iterables.limit(features, features.size() - 1)); - generateFeatures = ImmutableSet.of(Iterables.getLast(features)); + generateFeatures = ImmutableSet.of(features.asList().get(features.size() - 1)); superClass = ParameterizedTypeName.get(ClassName.get(PACKAGE_NAME, encode(Feature.makeClassName(parentFeatures))), kTypeVar, vTypeVar); } var context = new NodeContext(superClass, className, isFinal, parentFeatures, generateFeatures); for (NodeRule rule : rules) { - rule.accept(context); + if (rule.applies(context)) { + rule.execute(context); + } } - return context.nodeSubtype.build(); + return context.build(); } private Set> combinations() { diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java index e0c0ed3a84..9fa97b5b8b 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddConstructor.java @@ -16,10 +16,12 @@ package com.github.benmanes.caffeine.cache.local; import static com.github.benmanes.caffeine.cache.Specifications.ASYNC_CACHE_LOADER_PARAM; -import static com.github.benmanes.caffeine.cache.Specifications.LOCAL_CACHE_FACTORY; import static com.github.benmanes.caffeine.cache.Specifications.BOUNDED_LOCAL_CACHE; import static com.github.benmanes.caffeine.cache.Specifications.BUILDER_PARAM; +import static com.github.benmanes.caffeine.cache.Specifications.LOCAL_CACHE_FACTORY; + import javax.lang.model.element.Modifier; + import com.squareup.javapoet.FieldSpec; /** @@ -27,15 +29,15 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddConstructor extends LocalCacheRule { +public final class AddConstructor implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return true; } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.constructor .addParameter(BUILDER_PARAM) .addParameter(ASYNC_CACHE_LOADER_PARAM) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddDeques.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddDeques.java index 7a453ccea2..ebfef800d2 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddDeques.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddDeques.java @@ -28,21 +28,21 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddDeques extends LocalCacheRule { +public final class AddDeques implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return true; } @Override - protected void execute() { - addAccessOrderWindowDeque(); - addAccessOrderMainDeque(); - addWriteOrderDeque(); + public void execute(LocalCacheContext context) { + addAccessOrderWindowDeque(context); + addAccessOrderMainDeque(context); + addWriteOrderDeque(context); } - private void addAccessOrderWindowDeque() { + private void addAccessOrderWindowDeque(LocalCacheContext context) { if (Feature.usesAccessOrderWindowDeque(context.parentFeatures) || !Feature.usesAccessOrderWindowDeque(context.generateFeatures)) { return; @@ -51,39 +51,39 @@ private void addAccessOrderWindowDeque() { context.constructor.addStatement( "this.$L = builder.evicts() || builder.expiresAfterAccess()\n? new $T()\n: null", "accessOrderWindowDeque", ACCESS_ORDER_DEQUE); - addFieldAndMethod(ACCESS_ORDER_DEQUE, "accessOrderWindowDeque"); + addFieldAndMethod(context, ACCESS_ORDER_DEQUE, "accessOrderWindowDeque"); context.suppressedWarnings.add("NullAway"); } - private void addAccessOrderMainDeque() { + private void addAccessOrderMainDeque(LocalCacheContext context) { if (Feature.usesAccessOrderMainDeque(context.parentFeatures) || !Feature.usesAccessOrderMainDeque(context.generateFeatures)) { return; } - addDeque(ACCESS_ORDER_DEQUE, "accessOrderProbationDeque"); - addDeque(ACCESS_ORDER_DEQUE, "accessOrderProtectedDeque"); + addDeque(context, ACCESS_ORDER_DEQUE, "accessOrderProbationDeque"); + addDeque(context, ACCESS_ORDER_DEQUE, "accessOrderProtectedDeque"); context.suppressedWarnings.add("NullAway"); } - private void addWriteOrderDeque() { + private void addWriteOrderDeque(LocalCacheContext context) { if (Feature.usesWriteOrderDeque(context.parentFeatures) || !Feature.usesWriteOrderDeque(context.generateFeatures)) { return; } - addDeque(WRITE_ORDER_DEQUE, "writeOrderDeque"); + addDeque(context, WRITE_ORDER_DEQUE, "writeOrderDeque"); context.suppressedWarnings.add("NullAway"); } - private void addDeque(TypeName type, String name) { - addConstructor(type, name); - addFieldAndMethod(type, name); + private void addDeque(LocalCacheContext context, TypeName type, String name) { + addConstructor(context, type, name); + addFieldAndMethod(context, type, name); } - private void addConstructor(TypeName type, String name) { + private void addConstructor(LocalCacheContext context, TypeName type, String name) { context.constructor.addStatement("this.$L = new $T()", name, type); } - private void addFieldAndMethod(TypeName type, String name) { + private void addFieldAndMethod(LocalCacheContext context, TypeName type, String name) { context.cache.addField(FieldSpec.builder(type, name, Modifier.FINAL).build()); context.cache.addMethod(MethodSpec.methodBuilder(name) .addModifiers(context.protectedFinalModifiers()) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpirationTicker.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpirationTicker.java index 0be3457b33..152d313099 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpirationTicker.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpirationTicker.java @@ -26,16 +26,16 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddExpirationTicker extends LocalCacheRule { +public final class AddExpirationTicker implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return !(Feature.usesExpirationTicker(context.parentFeatures) || !Feature.usesExpirationTicker(context.generateFeatures)); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.constructor.addStatement("this.ticker = builder.getTicker()"); context.cache.addField(FieldSpec.builder(TICKER, "ticker", Modifier.FINAL).build()); context.cache.addMethod(MethodSpec.methodBuilder("expirationTicker") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterAccess.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterAccess.java index f7cbad5f67..8e07e9a766 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterAccess.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterAccess.java @@ -27,21 +27,21 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddExpireAfterAccess extends LocalCacheRule { +public final class AddExpireAfterAccess implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return context.generateFeatures.contains(Feature.EXPIRE_ACCESS); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.suppressedWarnings.add("NullAway"); - variableExpiration(); - fixedExpiration(); + variableExpiration(context); + fixedExpiration(context); } - private void fixedExpiration() { + private void fixedExpiration(LocalCacheContext context) { context.constructor.addStatement( "this.expiresAfterAccessNanos = builder.getExpiresAfterAccessNanos()"); context.cache.addField(FieldSpec.builder(long.class, "expiresAfterAccessNanos") @@ -63,7 +63,7 @@ private void fixedExpiration() { .build()); } - private void variableExpiration() { + private void variableExpiration(LocalCacheContext context) { context.cache.addMethod(MethodSpec.methodBuilder("expiresVariable") .addModifiers(context.protectedFinalModifiers()) .addStatement("return (timerWheel != null)") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterWrite.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterWrite.java index c5c5a86c18..2b99eee30a 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterWrite.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddExpireAfterWrite.java @@ -24,15 +24,15 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddExpireAfterWrite extends LocalCacheRule { +public final class AddExpireAfterWrite implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return context.generateFeatures.contains(Feature.EXPIRE_WRITE); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.constructor.addStatement( "this.expiresAfterWriteNanos = builder.getExpiresAfterWriteNanos()"); context.cache.addField(FieldSpec.builder(long.class, "expiresAfterWriteNanos") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddFastPath.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddFastPath.java index ecdc43012d..d24f0ae2ed 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddFastPath.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddFastPath.java @@ -24,10 +24,10 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddFastPath extends LocalCacheRule { +public final class AddFastPath implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { boolean parentFastPath = Feature.usesFastPath(context.parentFeatures); boolean fastpath = Feature.usesFastPath(Sets.union( context.parentFeatures, context.generateFeatures)); @@ -35,7 +35,7 @@ protected boolean applies() { } @Override - protected void execute() { + public void execute(LocalCacheContext context) { boolean fastpath = Feature.usesFastPath(Sets.union( context.parentFeatures, context.generateFeatures)); context.cache.addMethod(MethodSpec.methodBuilder("fastpath") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddKeyValueStrength.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddKeyValueStrength.java index 099cee0a5f..225b5e4723 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddKeyValueStrength.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddKeyValueStrength.java @@ -28,33 +28,34 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddKeyValueStrength extends LocalCacheRule { +public final class AddKeyValueStrength implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return true; } @Override - protected void execute() { - addKeyStrength(); - addValueStrength(); + public void execute(LocalCacheContext context) { + addKeyStrength(context); + addValueStrength(context); } - private void addKeyStrength() { + private void addKeyStrength(LocalCacheContext context) { if (context.generateFeatures.contains(Feature.WEAK_KEYS)) { - addStrength("collectKeys", "keyReferenceQueue", kRefQueueType); + addStrength(context, "collectKeys", "keyReferenceQueue", kRefQueueType); } } - private void addValueStrength() { + private void addValueStrength(LocalCacheContext context) { if (context.generateFeatures.contains(Feature.INFIRM_VALUES)) { - addStrength("collectValues", "valueReferenceQueue", vRefQueueType); + addStrength(context, "collectValues", "valueReferenceQueue", vRefQueueType); } } /** Adds the reference strength methods for the key or value. */ - private void addStrength(String collectName, String queueName, TypeName type) { + private void addStrength(LocalCacheContext context, + String collectName, String queueName, TypeName type) { context.cache.addMethod(MethodSpec.methodBuilder(queueName) .addModifiers(context.protectedFinalModifiers()) .returns(type) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddMaximum.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddMaximum.java index 25650b33c8..eecfbc6d65 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddMaximum.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddMaximum.java @@ -28,23 +28,23 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddMaximum extends LocalCacheRule { +public final class AddMaximum implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return !(Feature.usesMaximum(context.parentFeatures) || !Feature.usesMaximum(context.generateFeatures)); } @Override - protected void execute() { - addEvicts(); - addMaximumSize(); - addHillClimber(); - addFrequencySketch(); + public void execute(LocalCacheContext context) { + addEvicts(context); + addMaximumSize(context); + addHillClimber(context); + addFrequencySketch(context); } - private void addEvicts() { + private void addEvicts(LocalCacheContext context) { context.cache.addMethod(MethodSpec.methodBuilder("evicts") .addModifiers(context.protectedFinalModifiers()) .addStatement("return true") @@ -52,24 +52,24 @@ private void addEvicts() { .build()); } - private void addMaximumSize() { - addField(long.class, "maximum"); - addField(long.class, "weightedSize"); - addField(long.class, "windowMaximum"); - addField(long.class, "windowWeightedSize"); - addField(long.class, "mainProtectedMaximum"); - addField(long.class, "mainProtectedWeightedSize"); + private void addMaximumSize(LocalCacheContext context) { + addField(context, long.class, "maximum"); + addField(context, long.class, "weightedSize"); + addField(context, long.class, "windowMaximum"); + addField(context, long.class, "windowWeightedSize"); + addField(context, long.class, "mainProtectedMaximum"); + addField(context, long.class, "mainProtectedWeightedSize"); } - private void addHillClimber() { - addField(double.class, "stepSize"); - addField(long.class, "adjustment"); - addField(int.class, "hitsInSample"); - addField(int.class, "missesInSample"); - addField(double.class, "previousSampleHitRate"); + private void addHillClimber(LocalCacheContext context) { + addField(context, double.class, "stepSize"); + addField(context, long.class, "adjustment"); + addField(context, int.class, "hitsInSample"); + addField(context, int.class, "missesInSample"); + addField(context, double.class, "previousSampleHitRate"); } - private void addFrequencySketch() { + private void addFrequencySketch(LocalCacheContext context) { context.cache.addField(FieldSpec.builder( FREQUENCY_SKETCH, "sketch", Modifier.FINAL).build()); context.constructor.addCode(CodeBlock.builder() @@ -86,7 +86,7 @@ private void addFrequencySketch() { .build()); } - private void addField(Class type, String name) { + private void addField(LocalCacheContext context, Class type, String name) { context.cache.addField(FieldSpec.builder(type, name).build()); context.cache.addMethod(MethodSpec.methodBuilder(name) .addModifiers(context.protectedFinalModifiers()) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddPacer.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddPacer.java index ccca3b0819..ded58fee93 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddPacer.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddPacer.java @@ -26,16 +26,16 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddPacer extends LocalCacheRule { +public final class AddPacer implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return !(Feature.usesExpiration(context.parentFeatures) || !Feature.usesExpiration(context.generateFeatures)); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.constructor.addStatement("this.pacer = ($1L == $2L)\n? null\n: new Pacer($1L)", "builder.getScheduler()", "Scheduler.disabledScheduler()"); context.cache.addField(FieldSpec.builder(PACER, "pacer", Modifier.FINAL).build()); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRefreshAfterWrite.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRefreshAfterWrite.java index 64cb019b30..7a97ceb362 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRefreshAfterWrite.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRefreshAfterWrite.java @@ -24,15 +24,15 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddRefreshAfterWrite extends LocalCacheRule { +public final class AddRefreshAfterWrite implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return context.generateFeatures.contains(Feature.REFRESH_WRITE); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.constructor.addStatement( "this.refreshAfterWriteNanos = builder.getRefreshAfterWriteNanos()"); context.cache.addField(FieldSpec.builder(long.class, "refreshAfterWriteNanos") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRemovalListener.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRemovalListener.java index 1296d03329..214dd01adc 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRemovalListener.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddRemovalListener.java @@ -26,15 +26,15 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddRemovalListener extends LocalCacheRule { +public final class AddRemovalListener implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return context.generateFeatures.contains(Feature.LISTENING); } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.suppressedWarnings.add("NullAway"); context.cache.addField( FieldSpec.builder(REMOVAL_LISTENER, "removalListener", Modifier.FINAL).build()); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddStats.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddStats.java index f9c6868b83..57bce1ec05 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddStats.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddStats.java @@ -27,21 +27,21 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddStats extends LocalCacheRule { +public final class AddStats implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return context.generateFeatures.contains(Feature.STATS); } @Override - protected void execute() { - addIsRecording(); - addStatsTicker(); - addStatsCounter(); + public void execute(LocalCacheContext context) { + addIsRecording(context); + addStatsTicker(context); + addStatsCounter(context); } - private void addIsRecording() { + private void addIsRecording(LocalCacheContext context) { context.cache.addMethod(MethodSpec.methodBuilder("isRecordingStats") .addModifiers(context.publicFinalModifiers()) .addStatement("return true") @@ -49,7 +49,7 @@ private void addIsRecording() { .build()); } - private void addStatsCounter() { + private void addStatsCounter(LocalCacheContext context) { context.constructor.addStatement("this.statsCounter = builder.getStatsCounterSupplier().get()"); context.cache.addField(FieldSpec.builder( STATS_COUNTER, "statsCounter", Modifier.FINAL).build()); @@ -60,7 +60,7 @@ private void addStatsCounter() { .build()); } - private void addStatsTicker() { + private void addStatsTicker(LocalCacheContext context) { context.cache.addMethod(MethodSpec.methodBuilder("statsTicker") .addModifiers(context.publicFinalModifiers()) .addStatement("return $T.systemTicker()", TICKER) diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddSubtype.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddSubtype.java index 9ce61e70e1..5c91cd3a6c 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddSubtype.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/AddSubtype.java @@ -28,18 +28,18 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddSubtype extends LocalCacheRule { +public final class AddSubtype implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return true; } @Override - protected void execute() { + public void execute(LocalCacheContext context) { context.suppressedWarnings.add("MissingOverride"); context.cache.superclass(context.superClass) - .addJavadoc(getJavaDoc()) + .addJavadoc(getJavaDoc(context)) .addTypeVariable(kTypeVar) .addTypeVariable(vTypeVar); if (context.isFinal) { @@ -47,7 +47,7 @@ protected void execute() { } } - private String getJavaDoc() { + private String getJavaDoc(LocalCacheContext context) { StringBuilder doc = new StringBuilder(200); doc.append("WARNING: GENERATED CODE\n\n" + "A cache that provides the following features:\n
    "); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/Finalize.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/Finalize.java index e7002ac409..585574411b 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/Finalize.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/Finalize.java @@ -22,15 +22,15 @@ /** * @author ben.manes@gmail.com (Ben Manes) */ -public final class Finalize extends LocalCacheRule { +public final class Finalize implements LocalCacheRule { @Override - protected boolean applies() { + public boolean applies(LocalCacheContext context) { return true; } @Override - protected void execute() { + public void execute(LocalCacheContext context) { if (!context.suppressedWarnings.isEmpty()) { var format = (context.suppressedWarnings.size() == 1) ? "$S" diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheContext.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheContext.java index 29d7ee564a..2feff4a119 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheContext.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheContext.java @@ -31,14 +31,14 @@ * @author ben.manes@gmail.com (Ben Manes) */ public final class LocalCacheContext { - public final boolean isFinal; - public final String className; - public final TypeName superClass; - public final TypeSpec.Builder cache; - public final MethodSpec.Builder constructor; - public final Set suppressedWarnings; - public final ImmutableSet parentFeatures; - public final ImmutableSet generateFeatures; + final boolean isFinal; + final String className; + final TypeName superClass; + final TypeSpec.Builder cache; + final MethodSpec.Builder constructor; + final Set suppressedWarnings; + final ImmutableSet parentFeatures; + final ImmutableSet generateFeatures; public LocalCacheContext(TypeName superClass, String className, boolean isFinal, Set parentFeatures, Set generateFeatures) { @@ -52,6 +52,10 @@ public LocalCacheContext(TypeName superClass, String className, boolean isFinal, this.generateFeatures = Sets.immutableEnumSet(generateFeatures); } + public TypeSpec build() { + return cache.build(); + } + public Modifier[] publicFinalModifiers() { return isFinal ? new Modifier[] { Modifier.PUBLIC } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheRule.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheRule.java index c08b5a8c09..9b2209132e 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheRule.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/local/LocalCacheRule.java @@ -15,29 +15,16 @@ */ package com.github.benmanes.caffeine.cache.local; -import java.util.function.Consumer; - /** * A code generation rule for a cache. * * @author ben.manes@gmail.com (Ben Manes) */ -public abstract class LocalCacheRule implements Consumer { - protected LocalCacheContext context; - - @SuppressWarnings({"NullAway.Init", "PMD.UnnecessaryConstructor"}) - LocalCacheRule() {} - - @Override - public void accept(LocalCacheContext context) { - this.context = context; - if (applies()) { - execute(); - } - } +public interface LocalCacheRule { /** Returns if the rule should be executed. */ - protected abstract boolean applies(); + boolean applies(LocalCacheContext context); - protected abstract void execute(); + /** Modifies the context. */ + void execute(LocalCacheContext context); } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddConstructors.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddConstructors.java index 3b9d2e5c66..ddc7fc9dff 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddConstructors.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddConstructors.java @@ -16,8 +16,6 @@ package com.github.benmanes.caffeine.cache.node; import static com.github.benmanes.caffeine.cache.Specifications.keyRefQueueSpec; -import static com.github.benmanes.caffeine.cache.Specifications.keyRefSpec; -import static com.github.benmanes.caffeine.cache.Specifications.keySpec; import static com.github.benmanes.caffeine.cache.Specifications.valueRefQueueSpec; import static com.github.benmanes.caffeine.cache.Specifications.valueSpec; @@ -28,50 +26,41 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public final class AddConstructors extends NodeRule { +public final class AddConstructors implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { - addConstructorDefault(); - addConstructorByKey(); - addConstructorByKeyRef(); + public void execute(NodeContext context) { + addConstructorByKey(context); + addConstructorByKeyRef(context); context.suppressedWarnings.add("NullAway"); - if (isBaseClass()) { + if (context.isBaseClass()) { context.suppressedWarnings.add("PMD.UnusedFormalParameter"); } } - /** Adds the constructor used to create a factory. */ - private void addConstructorDefault() { - context.constructorDefault = MethodSpec.constructorBuilder(); - } - /** Adds the constructor by key to the node type. */ - private void addConstructorByKey() { - context.constructorByKey = MethodSpec.constructorBuilder().addParameter(keySpec); + private void addConstructorByKey(NodeContext context) { context.constructorByKey.addParameter(keyRefQueueSpec); addCommonParameters(context.constructorByKey); - if (isBaseClass()) { - callSiblingConstructor(); + if (context.isBaseClass()) { + callSiblingConstructor(context); } else { - callParentByKey(); + callParentByKey(context); } } /** Adds the constructor by key reference to the node type. */ - private void addConstructorByKeyRef() { - context.constructorByKeyRef = MethodSpec.constructorBuilder().addParameter(keyRefSpec); + private void addConstructorByKeyRef(NodeContext context) { addCommonParameters(context.constructorByKeyRef); - if (isBaseClass()) { - assignKeyRefAndValue(); + if (context.isBaseClass()) { + assignKeyRefAndValue(context); } else { - callParentByKeyRef(); + callParentByKeyRef(context); } } @@ -82,35 +71,35 @@ private void addCommonParameters(MethodSpec.Builder constructor) { constructor.addParameter(long.class, "now"); } - private void callSiblingConstructor() { - if (isStrongKeys()) { + private void callSiblingConstructor(NodeContext context) { + if (context.isStrongKeys()) { context.constructorByKey.addStatement("this(key, value, valueReferenceQueue, weight, now)"); } else { context.constructorByKey.addStatement( - "this(new $T($N, $N), value, valueReferenceQueue, weight, now)", keyReferenceType(), - "key", "keyReferenceQueue"); + "this(new $T($N, $N), value, valueReferenceQueue, weight, now)", + context.keyReferenceType(), "key", "keyReferenceQueue"); } } - private void assignKeyRefAndValue() { - if (isStrongValues()) { + private void assignKeyRefAndValue(NodeContext context) { + if (context.isStrongValues()) { context.constructorByKeyRef.addStatement("$L.set(this, $N)", - varHandleName("key"), "keyReference"); + context.varHandleName("key"), "keyReference"); context.constructorByKeyRef.addStatement("$L.set(this, $N)", - varHandleName("value"), "value"); + context.varHandleName("value"), "value"); } else { context.constructorByKeyRef.addStatement("$L.set(this, new $T($N, $N, $N))", - varHandleName("value"), valueReferenceType(), "keyReference", - "value", "valueReferenceQueue"); + context.varHandleName("value"), context.valueReferenceType(), + "keyReference", "value", "valueReferenceQueue"); } } - private void callParentByKey() { + private void callParentByKey(NodeContext context) { context.constructorByKey.addStatement( "super(key, keyReferenceQueue, value, valueReferenceQueue, weight, now)"); } - private void callParentByKeyRef() { + private void callParentByKeyRef(NodeContext context) { context.constructorByKeyRef.addStatement( "super(keyReference, value, valueReferenceQueue, weight, now)"); } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddDeques.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddDeques.java index 1a5b51110a..f43eb0dbf1 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddDeques.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddDeques.java @@ -18,37 +18,39 @@ import static com.github.benmanes.caffeine.cache.Specifications.NODE; import com.github.benmanes.caffeine.cache.Feature; +import com.github.benmanes.caffeine.cache.node.NodeContext.Strength; +import com.github.benmanes.caffeine.cache.node.NodeContext.Visibility; /** * Adds the access and write deques, if needed, to the node. * * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddDeques extends NodeRule { +public final class AddDeques implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { + public void execute(NodeContext context) { if (!Feature.usesAccessOrderWindowDeque(context.parentFeatures) && Feature.usesAccessOrderWindowDeque(context.generateFeatures)) { - addFieldAndGetter("previousInAccessOrder"); - addFieldAndGetter("nextInAccessOrder"); + addFieldAndGetter(context, "previousInAccessOrder"); + addFieldAndGetter(context, "nextInAccessOrder"); } if (!Feature.usesWriteOrderDeque(context.parentFeatures) && Feature.usesWriteOrderDeque(context.generateFeatures)) { - addFieldAndGetter("previousInWriteOrder"); - addFieldAndGetter("nextInWriteOrder"); + addFieldAndGetter(context, "previousInWriteOrder"); + addFieldAndGetter(context, "nextInWriteOrder"); } } /** Adds a simple field, accessor, and mutator for the variable. */ - private void addFieldAndGetter(String varName) { + private void addFieldAndGetter(NodeContext context, String varName) { context.nodeSubtype.addField(NODE, varName) - .addMethod(newGetter(Strength.STRONG, NODE, varName, Visibility.VOLATILE)) - .addMethod(newSetter(NODE, varName, Visibility.VOLATILE)); + .addMethod(context.newGetter(Strength.STRONG, NODE, varName, Visibility.VOLATILE)) + .addMethod(context.newSetter(NODE, varName, Visibility.VOLATILE)); } } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddExpiration.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddExpiration.java index 3a90895ad7..ee8bf4ea4e 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddExpiration.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddExpiration.java @@ -21,6 +21,8 @@ import javax.lang.model.element.Modifier; import com.github.benmanes.caffeine.cache.Feature; +import com.github.benmanes.caffeine.cache.node.NodeContext.Strength; +import com.github.benmanes.caffeine.cache.node.NodeContext.Visibility; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; @@ -29,42 +31,41 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public final class AddExpiration extends NodeRule { +public final class AddExpiration implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { - addVariableExpiration(); - addAccessExpiration(); - addWriteExpiration(); - addRefreshExpiration(); + public void execute(NodeContext context) { + addVariableExpiration(context); + addAccessExpiration(context); + addWriteExpiration(context); + addRefreshExpiration(context); } - private void addVariableExpiration() { + private void addVariableExpiration(NodeContext context) { if (context.generateFeatures.contains(Feature.EXPIRE_ACCESS)) { - addLink("previousInVariableOrder", "previousInAccessOrder"); - addLink("nextInVariableOrder", "nextInAccessOrder"); - addVariableTime("accessTime"); + addLink(context, "previousInVariableOrder", "previousInAccessOrder"); + addLink(context, "nextInVariableOrder", "nextInAccessOrder"); + addVariableTime(context, "accessTime"); } else if (context.generateFeatures.contains(Feature.EXPIRE_WRITE)) { - addLink("previousInVariableOrder", "previousInWriteOrder"); - addLink("nextInVariableOrder", "nextInWriteOrder"); - addVariableTime("writeTime"); + addLink(context, "previousInVariableOrder", "previousInWriteOrder"); + addLink(context, "nextInVariableOrder", "nextInWriteOrder"); + addVariableTime(context, "writeTime"); } if (context.parentFeatures.contains(Feature.EXPIRE_ACCESS) && context.parentFeatures.contains(Feature.EXPIRE_WRITE) && context.generateFeatures.contains(Feature.REFRESH_WRITE)) { - addLink("previousInVariableOrder", "previousInWriteOrder"); - addLink("nextInVariableOrder", "nextInWriteOrder"); - addVariableTime("accessTime"); + addLink(context, "previousInVariableOrder", "previousInWriteOrder"); + addLink(context, "nextInVariableOrder", "nextInWriteOrder"); + addVariableTime(context, "accessTime"); } } - private void addLink(String method, String varName) { + private void addLink(NodeContext context, String method, String varName) { var getter = MethodSpec.methodBuilder("get" + capitalize(method)) .addModifiers(Modifier.PUBLIC) .addStatement("return $N", varName) @@ -80,16 +81,16 @@ private void addLink(String method, String varName) { .addMethod(setter); } - private void addVariableTime(String varName) { + private void addVariableTime(NodeContext context, String varName) { var getter = MethodSpec.methodBuilder("getVariableTime") .addModifiers(Modifier.PUBLIC) - .addStatement("return (long) $L.getOpaque(this)", varHandleName(varName)) + .addStatement("return (long) $L.getOpaque(this)", context.varHandleName(varName)) .returns(long.class) .build(); var setter = MethodSpec.methodBuilder("setVariableTime") .addModifiers(Modifier.PUBLIC) .addParameter(long.class, varName) - .addStatement("$L.setOpaque(this, $N)", varHandleName(varName), varName) + .addStatement("$L.setOpaque(this, $N)", context.varHandleName(varName), varName) .build(); var cas = MethodSpec.methodBuilder("casVariableTime") .addModifiers(Modifier.PUBLIC) @@ -97,7 +98,7 @@ private void addVariableTime(String varName) { .addParameter(long.class, "update") .returns(boolean.class) .addStatement("return ($N == $N)\n&& $L.compareAndSet(this, $N, $N)", - varName, "expect", varHandleName(varName), "expect", "update") + varName, "expect", context.varHandleName(varName), "expect", "update") .build(); context.nodeSubtype .addMethod(getter) @@ -105,34 +106,36 @@ private void addVariableTime(String varName) { .addMethod(cas); } - private void addAccessExpiration() { + private void addAccessExpiration(NodeContext context) { if (!context.generateFeatures.contains(Feature.EXPIRE_ACCESS)) { return; } context.nodeSubtype .addField(long.class, "accessTime", Modifier.VOLATILE) - .addMethod(newGetter(Strength.STRONG, TypeName.LONG, "accessTime", Visibility.OPAQUE)) - .addMethod(newSetter(TypeName.LONG, "accessTime", Visibility.OPAQUE)); - addVarHandle("accessTime", TypeName.get(long.class)); - addTimeConstructorAssignment(context.constructorByKey, "accessTime", "now"); - addTimeConstructorAssignment(context.constructorByKeyRef, "accessTime", "now"); + .addMethod(context.newGetter(Strength.STRONG, + TypeName.LONG, "accessTime", Visibility.OPAQUE)) + .addMethod(context.newSetter(TypeName.LONG, "accessTime", Visibility.OPAQUE)); + context.addVarHandle("accessTime", TypeName.get(long.class)); + addTimeConstructorAssignment(context, context.constructorByKey, "accessTime", "now"); + addTimeConstructorAssignment(context, context.constructorByKeyRef, "accessTime", "now"); } - private void addWriteExpiration() { + private void addWriteExpiration(NodeContext context) { if (!Feature.useWriteTime(context.parentFeatures) && Feature.useWriteTime(context.generateFeatures)) { context.nodeSubtype .addField(long.class, "writeTime", Modifier.VOLATILE) - .addMethod(newGetter(Strength.STRONG, TypeName.LONG, "writeTime", Visibility.OPAQUE)) - .addMethod(newSetter(TypeName.LONG, "writeTime", Visibility.PLAIN)); - addVarHandle("writeTime", TypeName.get(long.class)); - addTimeConstructorAssignment(context.constructorByKey, "writeTime", "now & ~1L"); - addTimeConstructorAssignment(context.constructorByKeyRef, "writeTime", "now & ~1L"); + .addMethod(context.newGetter(Strength.STRONG, + TypeName.LONG, "writeTime", Visibility.OPAQUE)) + .addMethod(context.newSetter(TypeName.LONG, "writeTime", Visibility.PLAIN)); + context.addVarHandle("writeTime", TypeName.get(long.class)); + addTimeConstructorAssignment(context, context.constructorByKey, "writeTime", "now & ~1L"); + addTimeConstructorAssignment(context, context.constructorByKeyRef, "writeTime", "now & ~1L"); } } - private void addRefreshExpiration() { + private void addRefreshExpiration(NodeContext context) { if (!context.generateFeatures.contains(Feature.REFRESH_WRITE)) { return; } @@ -142,13 +145,13 @@ private void addRefreshExpiration() { .addParameter(long.class, "update") .returns(boolean.class) .addStatement("return ($N == $N)\n&& $L.compareAndSet(this, $N, $N)", - "writeTime", "expect", varHandleName("writeTime"), "expect", "update") + "writeTime", "expect", context.varHandleName("writeTime"), "expect", "update") .build()); } /** Adds a long constructor assignment. */ - private void addTimeConstructorAssignment( + private void addTimeConstructorAssignment(NodeContext context, MethodSpec.Builder constructor, String field, String value) { - constructor.addStatement("$L.set(this, $N)", varHandleName(field), value); + constructor.addStatement("$L.set(this, $N)", context.varHandleName(field), value); } } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddFactoryMethods.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddFactoryMethods.java index e582c5f08d..bb1a844b04 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddFactoryMethods.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddFactoryMethods.java @@ -34,28 +34,28 @@ /** * @author github.com/jvassev (Julian Vassev) */ -public final class AddFactoryMethods extends NodeRule { +public final class AddFactoryMethods implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { - addFactories(); + public void execute(NodeContext context) { + addFactories(context); if (context.generateFeatures.contains(Feature.WEAK_KEYS)) { - addWeakKeys(); + addWeakKeys(context); } if (context.generateFeatures.contains(Feature.WEAK_VALUES)) { - addWeakValues(); + addWeakValues(context); } else if (context.generateFeatures.contains(Feature.SOFT_VALUES)) { - addSoftValues(); + addSoftValues(context); } } - private void addFactories() { + private void addFactories(NodeContext context) { context.nodeSubtype.addMethod( newNode(keySpec, keyRefQueueSpec) .addStatement("return new $N<>(key, keyReferenceQueue, value, " @@ -68,7 +68,7 @@ private void addFactories() { .build()); } - private void addWeakKeys() { + private void addWeakKeys(NodeContext context) { context.nodeSubtype.addMethod(MethodSpec.methodBuilder("newLookupKey") .addModifiers(Modifier.PUBLIC) .addParameter(Object.class, "key") @@ -84,7 +84,7 @@ private void addWeakKeys() { .build()); } - private void addSoftValues() { + private void addSoftValues(NodeContext context) { context.nodeSubtype.addMethod(MethodSpec.methodBuilder("softValues") .addModifiers(Modifier.PUBLIC) .addStatement("return true") @@ -92,7 +92,7 @@ private void addSoftValues() { .build()); } - private void addWeakValues() { + private void addWeakValues(NodeContext context) { context.nodeSubtype.addMethod(MethodSpec.methodBuilder("weakValues") .addModifiers(Modifier.PUBLIC) .addStatement("return true") diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddHealth.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddHealth.java index 16514ba320..5ff212e874 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddHealth.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddHealth.java @@ -21,6 +21,7 @@ import static com.github.benmanes.caffeine.cache.Specifications.RETIRED_WEAK_KEY; import static com.github.benmanes.caffeine.cache.Specifications.referenceType; +import com.github.benmanes.caffeine.cache.node.NodeContext.Strength; import com.squareup.javapoet.MethodSpec; /** @@ -28,18 +29,18 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddHealth extends NodeRule { +public final class AddHealth implements NodeRule { @Override - protected boolean applies() { - return isBaseClass(); + public boolean applies(NodeContext context) { + return context.isBaseClass(); } @Override - protected void execute() { + public void execute(NodeContext context) { String retiredArg; String deadArg; - if (keyStrength() == Strength.STRONG) { + if (context.keyStrength() == Strength.STRONG) { retiredArg = RETIRED_STRONG_KEY; deadArg = DEAD_STRONG_KEY; } else { @@ -53,11 +54,12 @@ protected void execute() { .addModifiers(context.publicFinalModifiers()) .returns(boolean.class) .build()); - addState("isRetired", "retire", retiredArg, false); - addState("isDead", "die", deadArg, true); + addState(context, "isRetired", "retire", retiredArg, false); + addState(context, "isDead", "die", deadArg, true); } - private void addState(String checkName, String actionName, String arg, boolean finalized) { + private void addState(NodeContext context, String checkName + , String actionName, String arg, boolean finalized) { context.nodeSubtype.addMethod(MethodSpec.methodBuilder(checkName) .addStatement("return (getKeyReference() == $L)", arg) .addModifiers(context.publicFinalModifiers()) @@ -66,20 +68,20 @@ private void addState(String checkName, String actionName, String arg, boolean f var action = MethodSpec.methodBuilder(actionName) .addModifiers(context.publicFinalModifiers()); - if (valueStrength() == Strength.STRONG) { - if (keyStrength() != Strength.STRONG) { + if (context.valueStrength() == Strength.STRONG) { + if (context.keyStrength() != Strength.STRONG) { action.addStatement("key.clear()"); } // Set the value to null only when dead, as otherwise the explicit removal of an expired async // value will be notified as explicit rather than expired due to the isComputingAsync() check if (finalized) { - action.addStatement("$L.set(this, null)", varHandleName("value")); + action.addStatement("$L.set(this, null)", context.varHandleName("value")); } - action.addStatement("$L.set(this, $N)", varHandleName("key"), arg); + action.addStatement("$L.set(this, $N)", context.varHandleName("key"), arg); } else { action.addStatement("$1T valueRef = ($1T) $2L.get(this)", - valueReferenceType(), varHandleName("value")); - if (keyStrength() != Strength.STRONG) { + context.valueReferenceType(), context.varHandleName("value")); + if (context.keyStrength() != Strength.STRONG) { action.addStatement("$1T keyRef = ($1T) valueRef.getKeyReference()", referenceType); action.addStatement("keyRef.clear()"); } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddKey.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddKey.java index be249eb0a2..bab6b1b24c 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddKey.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddKey.java @@ -22,6 +22,7 @@ import javax.lang.model.element.Modifier; +import com.github.benmanes.caffeine.cache.node.NodeContext.Visibility; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; @@ -31,42 +32,41 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public final class AddKey extends NodeRule { +public final class AddKey implements NodeRule { @Override - protected boolean applies() { - return isBaseClass(); + public boolean applies(NodeContext context) { + return context.isBaseClass(); } @Override - protected void execute() { - if (isStrongValues()) { - addIfStrongValue(); + public void execute(NodeContext context) { + if (context.isStrongValues()) { + addIfStrongValue(context); } else { - addIfCollectedValue(); + addIfCollectedValue(context); } } - private void addIfStrongValue() { - var fieldSpec = isStrongKeys() + private void addIfStrongValue(NodeContext context) { + var fieldSpec = context.isStrongKeys() ? FieldSpec.builder(kTypeVar, "key", Modifier.VOLATILE) - : FieldSpec.builder(keyReferenceType(), "key", Modifier.VOLATILE); + : FieldSpec.builder(context.keyReferenceType(), "key", Modifier.VOLATILE); context.nodeSubtype .addField(fieldSpec.build()) - .addMethod(newGetter(keyStrength(), kTypeVar, "key", Visibility.PLAIN)) - .addMethod(newGetRef("key")); - addVarHandle("key", isStrongKeys() + .addMethod(context.newGetter(context.keyStrength(), kTypeVar, "key", Visibility.PLAIN)) + .addMethod(context.newGetRef("key")); + context.addVarHandle("key", context.isStrongKeys() ? ClassName.get(Object.class) - : keyReferenceType().rawType); + : context.keyReferenceType().rawType); } - private void addIfCollectedValue() { + private void addIfCollectedValue(NodeContext context) { context.nodeSubtype.addMethod(MethodSpec.methodBuilder("getKeyReference") .addModifiers(context.publicFinalModifiers()) .returns(Object.class) .addStatement("$1T valueRef = ($1T) $2L.get(this)", - valueReferenceType(), varHandleName("value")) + context.valueReferenceType(), context.varHandleName("value")) .addStatement("return valueRef.getKeyReference()") .build()); @@ -74,8 +74,8 @@ private void addIfCollectedValue() { .addModifiers(context.publicFinalModifiers()) .returns(kTypeVar) .addStatement("$1T valueRef = ($1T) $2L.get(this)", - valueReferenceType(), varHandleName("value")); - if (isStrongKeys()) { + context.valueReferenceType(), context.varHandleName("value")); + if (context.isStrongKeys()) { getKey.addStatement("return ($T) valueRef.getKeyReference()", kTypeVar); } else { getKey.addStatement("$1T keyRef = ($1T) valueRef.getKeyReference()", referenceType); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddMaximum.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddMaximum.java index 49df8ea067..35fd7e0979 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddMaximum.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddMaximum.java @@ -16,6 +16,8 @@ package com.github.benmanes.caffeine.cache.node; import com.github.benmanes.caffeine.cache.Feature; +import com.github.benmanes.caffeine.cache.node.NodeContext.Strength; +import com.github.benmanes.caffeine.cache.node.NodeContext.Visibility; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; @@ -24,21 +26,20 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public final class AddMaximum extends NodeRule { +public final class AddMaximum implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return Feature.usesMaximum(context.generateFeatures); } @Override - protected void execute() { - addQueueFlag(); - addWeight(); + public void execute(NodeContext context) { + addQueueFlag(context); + addWeight(context); } - private void addQueueFlag() { + private void addQueueFlag(NodeContext context) { context.nodeSubtype.addField(int.class, "queueType"); context.nodeSubtype.addMethod(MethodSpec.methodBuilder("getQueueType") .addModifiers(context.publicFinalModifiers()) @@ -52,18 +53,20 @@ private void addQueueFlag() { .build()); } - private void addWeight() { + private void addWeight(NodeContext context) { if (!context.generateFeatures.contains(Feature.MAXIMUM_WEIGHT)) { return; } context.nodeSubtype.addField(int.class, "weight") - .addMethod(newGetter(Strength.STRONG, TypeName.INT, "weight", Visibility.VOLATILE)) - .addMethod(newSetter(TypeName.INT, "weight", Visibility.VOLATILE)); + .addMethod(context.newGetter(Strength.STRONG, + TypeName.INT, "weight", Visibility.VOLATILE)) + .addMethod(context.newSetter(TypeName.INT, "weight", Visibility.VOLATILE)); context.constructorByKey.addStatement("this.$N = $N", "weight", "weight"); context.constructorByKeyRef.addStatement("this.$N = $N", "weight", "weight"); context.nodeSubtype.addField(int.class, "policyWeight") - .addMethod(newGetter(Strength.STRONG, TypeName.INT, "policyWeight", Visibility.VOLATILE)) - .addMethod(newSetter(TypeName.INT, "policyWeight", Visibility.VOLATILE)); + .addMethod(context.newGetter(Strength.STRONG, + TypeName.INT, "policyWeight", Visibility.VOLATILE)) + .addMethod(context.newSetter(TypeName.INT, "policyWeight", Visibility.VOLATILE)); } } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddSubtype.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddSubtype.java index ff02061e5f..921ea3d1c8 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddSubtype.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddSubtype.java @@ -24,31 +24,30 @@ import com.github.benmanes.caffeine.cache.Feature; import com.google.common.base.CaseFormat; -import com.squareup.javapoet.TypeSpec; /** * Adds the node inheritance hierarchy. * * @author ben.manes@gmail.com (Ben Manes) */ -public final class AddSubtype extends NodeRule { +public final class AddSubtype implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { + public void execute(NodeContext context) { context.suppressedWarnings.add("MissingOverride"); - context.nodeSubtype = TypeSpec.classBuilder(context.className) - .addJavadoc(getJavaDoc()) + context.nodeSubtype + .addJavadoc(getJavaDoc(context)) .addTypeVariable(kTypeVar) .addTypeVariable(vTypeVar); if (context.isFinal) { context.nodeSubtype.addModifiers(Modifier.FINAL); } - if (isBaseClass()) { + if (context.isBaseClass()) { context.nodeSubtype .superclass(NODE) .addSuperinterface(NODE_FACTORY); @@ -57,7 +56,7 @@ protected void execute() { } } - private String getJavaDoc() { + private String getJavaDoc(NodeContext context) { var doc = new StringBuilder(200); doc.append("WARNING: GENERATED CODE\n\n" + "A cache entry that provides the following features:\n
      "); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddValue.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddValue.java index dffe730a66..f6ba070661 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddValue.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/AddValue.java @@ -23,6 +23,7 @@ import javax.lang.model.element.Modifier; +import com.github.benmanes.caffeine.cache.node.NodeContext.Strength; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; @@ -33,44 +34,43 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings("PMD.AvoidDuplicateLiterals") -public final class AddValue extends NodeRule { +public final class AddValue implements NodeRule { @Override - protected boolean applies() { - return isBaseClass(); + public boolean applies(NodeContext context) { + return context.isBaseClass(); } @Override - protected void execute() { + public void execute(NodeContext context) { context.nodeSubtype - .addField(newValueField()) - .addMethod(makeGetValue()) - .addMethod(newGetRef("value")) - .addMethod(makeSetValue()) - .addMethod(makeContainsValue()); - if (isStrongValues()) { - addVarHandle("value", ClassName.get(Object.class)); + .addField(newValueField(context)) + .addMethod(makeGetValue(context)) + .addMethod(context.newGetRef("value")) + .addMethod(makeSetValue(context)) + .addMethod(makeContainsValue(context)); + if (context.isStrongValues()) { + context.addVarHandle("value", ClassName.get(Object.class)); } else { - addVarHandle("value", valueReferenceType().rawType); + context.addVarHandle("value", context.valueReferenceType().rawType); context.suppressedWarnings.add("NullAway"); } } - private FieldSpec newValueField() { - var fieldSpec = isStrongValues() + private FieldSpec newValueField(NodeContext context) { + var fieldSpec = context.isStrongValues() ? FieldSpec.builder(vTypeVar, "value", Modifier.VOLATILE) - : FieldSpec.builder(valueReferenceType(), "value", Modifier.VOLATILE); + : FieldSpec.builder(context.valueReferenceType(), "value", Modifier.VOLATILE); return fieldSpec.build(); } /** Creates the getValue method. */ - private MethodSpec makeGetValue() { + private MethodSpec makeGetValue(NodeContext context) { var getter = MethodSpec.methodBuilder("getValue") .addModifiers(context.publicFinalModifiers()) .returns(vTypeVar); - String handle = varHandleName("value"); - if (valueStrength() == Strength.STRONG) { + String handle = context.varHandleName("value"); + if (context.valueStrength() == Strength.STRONG) { getter.addStatement("return ($T) $L.get(this)", vTypeVar, handle); return getter.build(); } @@ -88,31 +88,32 @@ private MethodSpec makeGetValue() { } /** Creates the setValue method. */ - private MethodSpec makeSetValue() { + private MethodSpec makeSetValue(NodeContext context) { var setter = MethodSpec.methodBuilder("setValue") .addModifiers(context.publicFinalModifiers()) .addParameter(vTypeVar, "value") .addParameter(vRefQueueType, "referenceQueue"); - if (isStrongValues()) { - setter.addStatement("$L.setRelease(this, $N)", varHandleName("value"), "value"); + if (context.isStrongValues()) { + setter.addStatement("$L.setRelease(this, $N)", context.varHandleName("value"), "value"); } else { setter.addStatement("$1T ref = ($1T) $2L.get(this)", - Reference.class, varHandleName("value")); + Reference.class, context.varHandleName("value")); setter.addStatement("$L.setRelease(this, new $T($L, $N, referenceQueue))", - varHandleName("value"), valueReferenceType(), "getKeyReference()", "value"); + context.varHandleName("value"), context.valueReferenceType(), + "getKeyReference()", "value"); setter.addStatement("ref.clear()"); } return setter.build(); } - private MethodSpec makeContainsValue() { + private MethodSpec makeContainsValue(NodeContext context) { var containsValue = MethodSpec.methodBuilder("containsValue") .addModifiers(context.publicFinalModifiers()) .addParameter(Object.class, "value") .returns(boolean.class); - if (isStrongValues()) { + if (context.isStrongValues()) { containsValue.addStatement("return $T.equals(value, getValue())", Objects.class); } else { containsValue.addStatement("return getValue() == value"); diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/Finalize.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/Finalize.java index 67fb125beb..8f9e243892 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/Finalize.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/Finalize.java @@ -28,15 +28,15 @@ * * @author ben.manes@gmail.com (Ben Manes) */ -public class Finalize extends NodeRule { +public class Finalize implements NodeRule { @Override - protected boolean applies() { + public boolean applies(NodeContext context) { return true; } @Override - protected void execute() { + public void execute(NodeContext context) { if (!context.suppressedWarnings.isEmpty()) { var format = (context.suppressedWarnings.size() == 1) ? "$S" @@ -49,10 +49,10 @@ protected void execute() { .addMethod(context.constructorDefault.build()) .addMethod(context.constructorByKey.build()) .addMethod(context.constructorByKeyRef.build()); - addStaticBlock(); + addStaticBlock(context); } - private void addStaticBlock() { + private void addStaticBlock(NodeContext context) { if (context.varHandles.isEmpty()) { return; } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeContext.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeContext.java index 3a75cfce7e..675cda7301 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeContext.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeContext.java @@ -15,8 +15,19 @@ */ package com.github.benmanes.caffeine.cache.node; +import static com.github.benmanes.caffeine.cache.Specifications.NODE_FACTORY; +import static com.github.benmanes.caffeine.cache.Specifications.PACKAGE_NAME; +import static com.github.benmanes.caffeine.cache.Specifications.kTypeVar; +import static com.github.benmanes.caffeine.cache.Specifications.keyRefSpec; +import static com.github.benmanes.caffeine.cache.Specifications.keySpec; +import static com.github.benmanes.caffeine.cache.Specifications.vTypeVar; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Locale.US; import static java.util.Objects.requireNonNull; +import static org.apache.commons.lang3.StringUtils.capitalize; +import java.lang.invoke.VarHandle; +import java.lang.ref.Reference; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -26,10 +37,14 @@ import javax.lang.model.element.Modifier; import com.github.benmanes.caffeine.cache.Feature; +import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; @@ -37,20 +52,18 @@ * @author ben.manes@gmail.com (Ben Manes) */ public final class NodeContext { - public final boolean isFinal; - public final String className; - public final TypeName superClass; - public final Set suppressedWarnings; - public final ImmutableSet parentFeatures; - public final ImmutableSet generateFeatures; - public final List> varHandles; - - public TypeSpec.Builder nodeSubtype; - public MethodSpec.Builder constructorByKey; - public MethodSpec.Builder constructorByKeyRef; - public MethodSpec. Builder constructorDefault; - - @SuppressWarnings("NullAway.Init") + final boolean isFinal; + final String className; + final TypeName superClass; + final TypeSpec.Builder nodeSubtype; + final Set suppressedWarnings; + final MethodSpec.Builder constructorByKey; + final ImmutableSet parentFeatures; + final MethodSpec.Builder constructorDefault; + final MethodSpec.Builder constructorByKeyRef; + final ImmutableSet generateFeatures; + final List> varHandles; + public NodeContext(TypeName superClass, String className, boolean isFinal, Set parentFeatures, Set generateFeatures) { this.isFinal = isFinal; @@ -58,8 +71,16 @@ public NodeContext(TypeName superClass, String className, boolean isFinal, this.suppressedWarnings = new TreeSet<>(); this.className = requireNonNull(className); this.superClass = requireNonNull(superClass); + this.nodeSubtype = TypeSpec.classBuilder(className); + this.constructorDefault = MethodSpec.constructorBuilder(); this.parentFeatures = Sets.immutableEnumSet(parentFeatures); this.generateFeatures = Sets.immutableEnumSet(generateFeatures); + this.constructorByKey = MethodSpec.constructorBuilder().addParameter(keySpec); + this.constructorByKeyRef = MethodSpec.constructorBuilder().addParameter(keyRefSpec); + } + + public TypeSpec build() { + return nodeSubtype.build(); } public Modifier[] publicFinalModifiers() { @@ -67,4 +88,134 @@ public Modifier[] publicFinalModifiers() { ? new Modifier[] { Modifier.PUBLIC } : new Modifier[] { Modifier.PUBLIC, Modifier.FINAL }; } + + public boolean isBaseClass() { + return superClass.equals(TypeName.OBJECT); + } + + public Strength keyStrength() { + return Strength.of(generateFeatures.asList().get(0)); + } + + public Strength valueStrength() { + return Strength.of(generateFeatures.asList().get(1)); + } + + public boolean isStrongKeys() { + return parentFeatures.contains(Feature.STRONG_KEYS) + || generateFeatures.contains(Feature.STRONG_KEYS); + } + + public boolean isStrongValues() { + return parentFeatures.contains(Feature.STRONG_VALUES) + || generateFeatures.contains(Feature.STRONG_VALUES); + } + + public ParameterizedTypeName keyReferenceType() { + checkState(generateFeatures.contains(Feature.WEAK_KEYS)); + return ParameterizedTypeName.get( + ClassName.get(PACKAGE_NAME + ".References", "WeakKeyReference"), kTypeVar); + } + + public ParameterizedTypeName valueReferenceType() { + checkState(!generateFeatures.contains(Feature.STRONG_VALUES)); + String clazz = generateFeatures.contains(Feature.WEAK_VALUES) + ? "WeakValueReference" + : "SoftValueReference"; + return ParameterizedTypeName.get(ClassName.get(PACKAGE_NAME + ".References", clazz), vTypeVar); + } + + /** Creates a VarHandle to the instance field. */ + public void addVarHandle(String varName, TypeName type) { + String fieldName = varHandleName(varName); + nodeSubtype.addField(FieldSpec.builder(VarHandle.class, fieldName, + Modifier.PROTECTED, Modifier.STATIC, Modifier.FINAL).build()); + Consumer statement = builder -> builder + .addStatement("$L = lookup.findVarHandle($T.class, $L.$L, $T.class)", fieldName, + ClassName.bestGuess(className), NODE_FACTORY.rawType.simpleName(), + fieldName, type); + varHandles.add(statement); + } + + /** Creates an accessor that returns the reference. */ + public MethodSpec newGetRef(String varName) { + var getter = MethodSpec.methodBuilder("get" + capitalize(varName) + "Reference") + .addModifiers(publicFinalModifiers()) + .returns(Object.class); + getter.addStatement("return $L.get(this)", varHandleName(varName)); + return getter.build(); + } + + /** Creates an accessor that returns the unwrapped variable. */ + public MethodSpec newGetter(Strength strength, + TypeName varType, String varName, Visibility visibility) { + var getter = MethodSpec.methodBuilder("get" + capitalize(varName)) + .addModifiers(publicFinalModifiers()) + .returns(varType); + if (strength == Strength.STRONG) { + if (visibility == Visibility.PLAIN) { + var template = String.format(US, "return (%s) $L.get(this)", + varType.isPrimitive() ? "$L" : "$T"); + getter.addStatement(template, varType, varHandleName(varName)); + } else if (visibility == Visibility.OPAQUE) { + var template = String.format(US, "return (%s) $L.getOpaque(this)", + varType.isPrimitive() ? "$L" : "$T"); + getter.addStatement(template, varType, varHandleName(varName)); + } else if (visibility == Visibility.VOLATILE) { + getter.addStatement("return $N", varName); + } else { + throw new IllegalArgumentException(); + } + } else { + if (visibility == Visibility.PLAIN) { + getter.addStatement("return (($T<$T>) $L.get(this)).get()", + Reference.class, varType, varHandleName(varName)); + } else if (visibility == Visibility.VOLATILE) { + getter.addStatement("return $N.get()", varName); + } else { + throw new IllegalArgumentException(); + } + } + return getter.build(); + } + + /** Creates a mutator to the variable. */ + public MethodSpec newSetter(TypeName varType, String varName, Visibility visibility) { + String methodName = "set" + Character.toUpperCase(varName.charAt(0)) + varName.substring(1); + var setter = MethodSpec.methodBuilder(methodName) + .addModifiers(publicFinalModifiers()) + .addParameter(varType, varName); + if (visibility == Visibility.PLAIN) { + setter.addStatement("$L.set(this, $N)", varHandleName(varName), varName); + } else if (visibility == Visibility.OPAQUE) { + setter.addStatement("$L.setOpaque(this, $N)", varHandleName(varName), varName); + } else if (visibility == Visibility.VOLATILE) { + setter.addStatement("this.$N = $N", varName, varName); + } else { + throw new IllegalArgumentException(); + } + return setter.build(); + } + + /** Returns the name of the VarHandle to this variable. */ + public String varHandleName(String varName) { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, varName); + } + + public enum Visibility { + PLAIN, OPAQUE, VOLATILE + } + + public enum Strength { + STRONG, WEAK, SOFT; + + static Strength of(Feature feature) { + for (var strength : Strength.values()) { + if (feature.name().startsWith(strength.name())) { + return strength; + } + } + throw new IllegalStateException("No strength for " + feature); + } + } } diff --git a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeRule.java b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeRule.java index bd39ded2ea..2a6b7fd268 100644 --- a/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeRule.java +++ b/caffeine/src/javaPoet/java/com/github/benmanes/caffeine/cache/node/NodeRule.java @@ -15,184 +15,16 @@ */ package com.github.benmanes.caffeine.cache.node; -import static com.github.benmanes.caffeine.cache.Specifications.NODE_FACTORY; -import static com.github.benmanes.caffeine.cache.Specifications.PACKAGE_NAME; -import static com.github.benmanes.caffeine.cache.Specifications.kTypeVar; -import static com.github.benmanes.caffeine.cache.Specifications.vTypeVar; -import static com.google.common.base.Preconditions.checkState; -import static java.util.Locale.US; -import static org.apache.commons.lang3.StringUtils.capitalize; - -import java.lang.invoke.VarHandle; -import java.lang.ref.Reference; -import java.util.function.Consumer; - -import javax.lang.model.element.Modifier; - -import com.github.benmanes.caffeine.cache.Feature; -import com.google.common.base.CaseFormat; -import com.google.common.collect.Iterables; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; - /** - * A code generation rule for a node. This class holds the common state and methods for rules to - * act upon and mutate. + * A code generation rule for a node. * * @author ben.manes@gmail.com (Ben Manes) */ -public abstract class NodeRule implements Consumer { - protected NodeContext context; - - @SuppressWarnings("NullAway.Init") - NodeRule() {} - - @Override - public final void accept(NodeContext context) { - this.context = context; - if (applies()) { - execute(); - } - } +public interface NodeRule { /** Returns if the rule should be executed. */ - protected abstract boolean applies(); - - protected abstract void execute(); - - protected boolean isBaseClass() { - return context.superClass.equals(TypeName.OBJECT); - } - - @SuppressWarnings("NullAway") - protected Strength keyStrength() { - return strengthOf(Iterables.get(context.generateFeatures, 0)); - } - - @SuppressWarnings("NullAway") - protected Strength valueStrength() { - return strengthOf(Iterables.get(context.generateFeatures, 1)); - } - - protected boolean isStrongKeys() { - return context.parentFeatures.contains(Feature.STRONG_KEYS) - || context.generateFeatures.contains(Feature.STRONG_KEYS); - } - - protected boolean isStrongValues() { - return context.parentFeatures.contains(Feature.STRONG_VALUES) - || context.generateFeatures.contains(Feature.STRONG_VALUES); - } - - protected ParameterizedTypeName keyReferenceType() { - checkState(context.generateFeatures.contains(Feature.WEAK_KEYS)); - return ParameterizedTypeName.get( - ClassName.get(PACKAGE_NAME + ".References", "WeakKeyReference"), kTypeVar); - } - - protected ParameterizedTypeName valueReferenceType() { - checkState(!context.generateFeatures.contains(Feature.STRONG_VALUES)); - String clazz = context.generateFeatures.contains(Feature.WEAK_VALUES) - ? "WeakValueReference" - : "SoftValueReference"; - return ParameterizedTypeName.get(ClassName.get(PACKAGE_NAME + ".References", clazz), vTypeVar); - } - - /** Returns the name of the VarHandle to this variable. */ - protected String varHandleName(String varName) { - return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, varName); - } - - /** Creates a VarHandle to the instance field. */ - public void addVarHandle(String varName, TypeName type) { - String fieldName = varHandleName(varName); - context.nodeSubtype.addField(FieldSpec.builder(VarHandle.class, fieldName, - Modifier.PROTECTED, Modifier.STATIC, Modifier.FINAL).build()); - Consumer statement = builder -> builder - .addStatement("$L = lookup.findVarHandle($T.class, $L.$L, $T.class)", fieldName, - ClassName.bestGuess(context.className), NODE_FACTORY.rawType.simpleName(), - fieldName, type); - context.varHandles.add(statement); - } - - /** Creates an accessor that returns the reference. */ - protected final MethodSpec newGetRef(String varName) { - var getter = MethodSpec.methodBuilder("get" + capitalize(varName) + "Reference") - .addModifiers(context.publicFinalModifiers()) - .returns(Object.class); - getter.addStatement("return $L.get(this)", varHandleName(varName)); - return getter.build(); - } - - /** Creates an accessor that returns the unwrapped variable. */ - protected final MethodSpec newGetter(Strength strength, TypeName varType, - String varName, Visibility visibility) { - var getter = MethodSpec.methodBuilder("get" + capitalize(varName)) - .addModifiers(context.publicFinalModifiers()) - .returns(varType); - if (strength == Strength.STRONG) { - if (visibility == Visibility.PLAIN) { - var template = String.format(US, "return (%s) $L.get(this)", - varType.isPrimitive() ? "$L" : "$T"); - getter.addStatement(template, varType, varHandleName(varName)); - } else if (visibility == Visibility.OPAQUE) { - var template = String.format(US, "return (%s) $L.getOpaque(this)", - varType.isPrimitive() ? "$L" : "$T"); - getter.addStatement(template, varType, varHandleName(varName)); - } else if (visibility == Visibility.VOLATILE) { - getter.addStatement("return $N", varName); - } else { - throw new IllegalArgumentException(); - } - } else { - if (visibility == Visibility.PLAIN) { - getter.addStatement("return (($T<$T>) $L.get(this)).get()", - Reference.class, varType, varHandleName(varName)); - } else if (visibility == Visibility.VOLATILE) { - getter.addStatement("return $N.get()", varName); - } else { - throw new IllegalArgumentException(); - } - } - return getter.build(); - } - - /** Creates a mutator to the variable. */ - protected final MethodSpec newSetter(TypeName varType, String varName, Visibility visibility) { - String methodName = "set" + Character.toUpperCase(varName.charAt(0)) + varName.substring(1); - var setter = MethodSpec.methodBuilder(methodName) - .addModifiers(context.publicFinalModifiers()) - .addParameter(varType, varName); - if (visibility == Visibility.PLAIN) { - setter.addStatement("$L.set(this, $N)", varHandleName(varName), varName); - } else if (visibility == Visibility.OPAQUE) { - setter.addStatement("$L.setOpaque(this, $N)", varHandleName(varName), varName); - } else if (visibility == Visibility.VOLATILE) { - setter.addStatement("this.$N = $N", varName, varName); - } else { - throw new IllegalArgumentException(); - } - return setter.build(); - } - - private Strength strengthOf(Feature feature) { - for (var strength : Strength.values()) { - if (feature.name().startsWith(strength.name())) { - return strength; - } - } - throw new IllegalStateException("No strength for " + feature); - } - - protected enum Strength { - STRONG, WEAK, SOFT - } + boolean applies(NodeContext context); - protected enum Visibility { - PLAIN, OPAQUE, VOLATILE - } + /** Modifies the context. */ + void execute(NodeContext context); } diff --git a/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/impl/CoherenceCache.java b/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/impl/CoherenceCache.java index 0ec4584219..6de8173ee3 100644 --- a/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/impl/CoherenceCache.java +++ b/caffeine/src/jmh/java/com/github/benmanes/caffeine/cache/impl/CoherenceCache.java @@ -15,25 +15,27 @@ */ package com.github.benmanes.caffeine.cache.impl; +import java.util.Map; + import com.github.benmanes.caffeine.cache.BasicCache; import com.tangosol.net.cache.LocalCache; /** * @author ben.manes@gmail.com (Ben Manes) */ -@SuppressWarnings({"deprecation", "unchecked"}) public final class CoherenceCache implements BasicCache { - @SuppressWarnings("PMD.LooseCoupling") - private final LocalCache cache; + private final Map cache; + @SuppressWarnings({"deprecation", "unchecked"}) public CoherenceCache(int maximumSize, int evictionPolicyType) { - cache = new LocalCache(Math.max(1, maximumSize)); + var cache = new LocalCache(Math.max(1, maximumSize)); cache.setEvictionType(evictionPolicyType); + this.cache = cache; } @Override public V get(K key) { - return (V) cache.get(key); + return cache.get(key); } @Override diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/AbstractLinkedDeque.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/AbstractLinkedDeque.java index cea06e0dd7..8d09f84d68 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/AbstractLinkedDeque.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/AbstractLinkedDeque.java @@ -174,7 +174,6 @@ public int size() { } @Override - @SuppressWarnings("PMD.AvoidReassigningLoopVariables") public void clear() { E e = first; while (e != null) { diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java index eeb046d854..6c8632432b 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/BoundedLocalCache.java @@ -1876,7 +1876,6 @@ final class AddTask implements Runnable { @Override @GuardedBy("evictionLock") - @SuppressWarnings("FutureReturnValueIgnored") public void run() { if (evicts()) { setWeightedSize(weightedSize() + weight); @@ -3964,7 +3963,6 @@ public Policy policy() { return (p == null) ? (policy = new BoundedPolicy<>(cache, identity(), cache.isWeighted)) : p; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -4471,7 +4469,6 @@ public Function mappingFunction() { return bulkMappingFunction; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -4528,7 +4525,6 @@ public Policy policy() { return policy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -4581,7 +4577,6 @@ public Policy policy() { return policy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } diff --git a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/UnboundedLocalCache.java b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/UnboundedLocalCache.java index c9bdc689db..798b770a6d 100644 --- a/caffeine/src/main/java/com/github/benmanes/caffeine/cache/UnboundedLocalCache.java +++ b/caffeine/src/main/java/com/github/benmanes/caffeine/cache/UnboundedLocalCache.java @@ -1045,7 +1045,6 @@ public Policy policy() { : policy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -1146,7 +1145,6 @@ Object writeReplace() { return proxy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -1196,7 +1194,6 @@ public Policy policy() { : policy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @@ -1250,7 +1247,6 @@ public Policy policy() { : policy; } - @SuppressWarnings("UnusedVariable") private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/BoundedLocalCacheTest.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/BoundedLocalCacheTest.java index 8fdbad4fea..9ef151b8a1 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/BoundedLocalCacheTest.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/BoundedLocalCacheTest.java @@ -236,7 +236,6 @@ public void clear_pendingWrites_weakKeys( /* --------------- Maintenance --------------- */ @Test - @SuppressWarnings("UnusedVariable") public void cleanupTask_allowGc() { var cache = new BoundedLocalCache( Caffeine.newBuilder(), /* loader */ null, /* async */ false) {}; diff --git a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/GuavaCacheFromContext.java b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/GuavaCacheFromContext.java index dc1d532f51..6272aeb884 100644 --- a/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/GuavaCacheFromContext.java +++ b/caffeine/src/test/java/com/github/benmanes/caffeine/cache/testing/GuavaCacheFromContext.java @@ -19,8 +19,6 @@ import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.requireNonNull; -import java.io.InvalidObjectException; -import java.io.ObjectInputStream; import java.io.Serializable; import java.util.AbstractMap.SimpleImmutableEntry; import java.util.Collections; @@ -436,12 +434,6 @@ public Set keySet() { protected ConcurrentMap delegate() { return cache.asMap(); } - - @SuppressWarnings({"UnusedMethod", "UnusedVariable"}) - private void readObject(ObjectInputStream stream) throws InvalidObjectException { - statsCounter = new SimpleStatsCounter(); - } - final class KeySetView extends ForwardingSet { @Override public boolean remove(Object o) { requireNonNull(o); diff --git a/gradle/config/pmd/rulesSets.xml b/gradle/config/pmd/rulesSets.xml index 2b871963ee..e3de7a3705 100644 --- a/gradle/config/pmd/rulesSets.xml +++ b/gradle/config/pmd/rulesSets.xml @@ -107,12 +107,6 @@ - - - - - - diff --git a/jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventDispatcher.java b/jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventDispatcher.java index 43e9376140..be6c30feee 100644 --- a/jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventDispatcher.java +++ b/jcache/src/main/java/com/github/benmanes/caffeine/jcache/event/EventDispatcher.java @@ -239,7 +239,6 @@ private void publish(Cache cache, EventType eventType, K key, JCacheEntryEvent e = event; var dispatchQueue = entry.getValue(); var future = dispatchQueue.compute(key, (k, queue) -> { - @SuppressWarnings("resource") Runnable action = () -> registration.getCacheEntryListener().dispatch(e); return (queue == null) ? CompletableFuture.runAsync(action, executor) diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/Simulate.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/Simulate.java index 297b34f96f..29b3073be7 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/Simulate.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/Simulate.java @@ -149,7 +149,6 @@ private enum Theme { } private static final class LongPreprocessor implements IParameterPreprocessor { - @SuppressWarnings("PMD.ReplaceVectorWithList") @Override public boolean preprocess(Stack args, CommandSpec commandSpec, ArgSpec argSpec, Map info) { args.replaceAll(arg -> arg.replace("_", "")); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/CoherencePolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/CoherencePolicy.java index 50c740b715..25ae0fad31 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/CoherencePolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/CoherencePolicy.java @@ -19,6 +19,7 @@ import static java.util.stream.Collectors.toUnmodifiableSet; import java.util.EnumSet; +import java.util.Map; import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; @@ -41,10 +42,10 @@ @SuppressWarnings("deprecation") @PolicySpec(name = "product.Coherence", characteristics = WEIGHTED) public final class CoherencePolicy implements Policy { + private final Map cache; private final PolicyStats policyStats; - @SuppressWarnings("PMD.LooseCoupling") - private final LocalCache cache; + @SuppressWarnings("unchecked") public CoherencePolicy(CoherenceSettings settings, Eviction policy) { policyStats = new PolicyStats(name() + " (%s)", policy); @@ -56,12 +57,13 @@ public CoherencePolicy(CoherenceSettings settings, Eviction policy) { factor *= 1024; } - cache = new LocalCache(); + var cache = new LocalCache(); cache.setUnitFactor(factor); cache.setHighUnits((int) maximum); cache.setEvictionType(policy.type); cache.addMapListener(new CoherenceListener()); cache.setUnitCalculator(new AccessEventCalculator()); + this.cache = cache; } /** Returns all variations of this policy based on the configuration parameters. */ @@ -74,7 +76,7 @@ public static Set policies(Config config) { @Override public void record(AccessEvent event) { - var value = (AccessEvent) cache.get(event.key()); + var value = cache.get(event.key()); if (value == null) { cache.put(event.key(), event); policyStats.recordWeightedMiss(event.weight()); diff --git a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/ExpiringMapPolicy.java b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/ExpiringMapPolicy.java index c84c752a04..21f1e32f00 100644 --- a/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/ExpiringMapPolicy.java +++ b/simulator/src/main/java/com/github/benmanes/caffeine/cache/simulator/policy/product/ExpiringMapPolicy.java @@ -18,6 +18,7 @@ import static java.util.stream.Collectors.toUnmodifiableSet; import java.util.EnumSet; +import java.util.Map; import java.util.Set; import com.github.benmanes.caffeine.cache.simulator.BasicSettings; @@ -38,15 +39,16 @@ */ @PolicySpec(name = "product.ExpiringMap") public final class ExpiringMapPolicy implements KeyOnlyPolicy { - @SuppressWarnings("PMD.LooseCoupling") - private final ExpiringMap cache; + private final Map cache; private final PolicyStats policyStats; + private final int maximumSize; public ExpiringMapPolicy(ExpiringMapSettings settings, Eviction policy) { policyStats = new PolicyStats(name() + " (%s)", policy); + maximumSize = Math.toIntExact(settings.maximumSize()); cache = ExpiringMap.builder() - .maxSize(Math.toIntExact(settings.maximumSize())) .expirationPolicy(policy.type) + .maxSize(maximumSize) .build(); } @@ -62,7 +64,7 @@ public static Set policies(Config config) { public void record(long key) { var value = cache.get(key); if (value == null) { - if (cache.size() == cache.getMaxSize()) { + if (cache.size() == maximumSize) { policyStats.recordEviction(); } cache.put(key, Boolean.TRUE);