Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5a71df8
Add more flexible configuration for Random Teleport.
vLuckyyy Nov 17, 2024
fc68d41
Complete configurations with missing unsafe blocks and air blocks
vLuckyyy Nov 18, 2024
cbb9d2e
Fix issues reported by @coderabbitai
vLuckyyy Nov 18, 2024
7d66781
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 18, 2024
a7d1c16
Resolve issues reported in review, create `RandomTeleportRadiusRepres…
vLuckyyy Nov 19, 2024
a270f2b
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 19, 2024
5e17616
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 19, 2024
5914aaf
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 19, 2024
f13cfdf
Add import.
vLuckyyy Nov 19, 2024
6ea96f7
Remvoe buttons, add height range
vLuckyyy Nov 19, 2024
2b271e8
Fix comments
vLuckyyy Nov 19, 2024
6c78d2a
Add teleportation counting.
vLuckyyy Nov 23, 2024
8d9a7a9
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 23, 2024
2b40148
Update eternalcore-core/src/main/java/com/eternalcode/core/feature/ra…
vLuckyyy Nov 23, 2024
49d94c3
Move description.
vLuckyyy Nov 23, 2024
3be765c
Rename some classes make API more usable.
Rollczi Nov 26, 2024
bd81e1a
Merge branch 'master' into expand-random-teleport
vLuckyyy Nov 29, 2024
2c8f248
Teleport players without waiting with the `/rtp <player> (admin comma…
vLuckyyy Nov 30, 2024
f190e79
Add migrations, rename configs
Rollczi Dec 9, 2024
ef9752c
Fix migration
Rollczi Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@

import java.time.Duration;
import java.time.Instant;
import java.util.function.Supplier;

public class Delay<T> {

private final Cache<T, Instant> delays;

private final DelaySettings delaySettings;
private final Supplier<Duration> delaySettings;

@Deprecated
public Delay(DelaySettings delaySettings) {
this.delaySettings = delaySettings;
this((Supplier<Duration>) () -> delaySettings.delay());
}
Comment on lines +16 to +19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add proper deprecation documentation and improve type safety

The deprecated constructor should include proper Javadoc with @deprecated and @since tags explaining the migration path. Also, the cast to Supplier<Duration> is unsafe and could be improved.

Consider this safer implementation:

 @Deprecated
+/**
+ * @deprecated Use {@link #Delay(Supplier)} instead.
+ * @since 1.0.0
+ */
 public Delay(DelaySettings delaySettings) {
+    Objects.requireNonNull(delaySettings, "delaySettings cannot be null");
     this((Supplier<Duration>) () -> delaySettings.delay());
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Deprecated
public Delay(DelaySettings delaySettings) {
this.delaySettings = delaySettings;
this((Supplier<Duration>) () -> delaySettings.delay());
}
@Deprecated
/**
* @deprecated Use {@link #Delay(Supplier)} instead.
* @since 1.0.0
*/
public Delay(DelaySettings delaySettings) {
Objects.requireNonNull(delaySettings, "delaySettings cannot be null");
this((Supplier<Duration>) () -> delaySettings.delay());
}


public Delay(Supplier<Duration> delayProvider) {
this.delaySettings = delayProvider;

this.delays = CacheBuilder.newBuilder()
.expireAfterWrite(delaySettings.delay())
.expireAfterWrite(delayProvider.get())
.build();
Comment on lines +21 to 26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null checks for the delay provider

The constructor should validate the supplier and its provided duration to prevent runtime errors.

Apply these changes:

 public Delay(Supplier<Duration> delayProvider) {
+    Objects.requireNonNull(delayProvider, "delayProvider cannot be null");
     this.delaySettings = delayProvider;
+    Duration initialDelay = Objects.requireNonNull(delayProvider.get(), 
+        "delay duration cannot be null");
 
     this.delays = CacheBuilder.newBuilder()
-        .expireAfterWrite(delayProvider.get())
+        .expireAfterWrite(initialDelay)
         .build();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public Delay(Supplier<Duration> delayProvider) {
this.delaySettings = delayProvider;
this.delays = CacheBuilder.newBuilder()
.expireAfterWrite(delaySettings.delay())
.expireAfterWrite(delayProvider.get())
.build();
public Delay(Supplier<Duration> delayProvider) {
Objects.requireNonNull(delayProvider, "delayProvider cannot be null");
this.delaySettings = delayProvider;
Duration initialDelay = Objects.requireNonNull(delayProvider.get(),
"delay duration cannot be null");
this.delays = CacheBuilder.newBuilder()
.expireAfterWrite(initialDelay)
.build();

}

Expand All @@ -25,7 +31,7 @@ public void markDelay(T key, Duration delay) {
}

public void markDelay(T key) {
this.markDelay(key, this.delaySettings.delay());
this.markDelay(key, this.delaySettings.get());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

🛠️ Refactor suggestion

Null check is needed, but duration consistency is by design

The null check suggestion is valid, but the concern about duration consistency is incorrect. The cache expiration is set only once during construction (CacheBuilder.newBuilder().expireAfterWrite(delayProvider.get())), while the delay marking uses the current supplier value. This is likely intentional to allow dynamic delay durations while maintaining a fixed cache cleanup schedule.

Here's the recommended implementation:

 public void markDelay(T key) {
-    this.markDelay(key, this.delaySettings.get());
+    Duration delay = Objects.requireNonNull(this.delaySettings.get(),
+        "delay duration cannot be null");
+    this.markDelay(key, delay);
 }
🔗 Analysis chain

Add null check and consider duration consistency

The method should validate the duration from the supplier. Also, there's a potential inconsistency if the supplier returns different durations over time, as the cache expiration might not match the marked delay.

Consider this implementation:

 public void markDelay(T key) {
-    this.markDelay(key, this.delaySettings.get());
+    Duration delay = Objects.requireNonNull(this.delaySettings.get(),
+        "delay duration cannot be null");
+    this.markDelay(key, delay);
 }

Let's check if the supplier is used consistently across the codebase:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for potential inconsistent usage of the delay supplier
ast-grep --pattern 'delaySettings.get()'

Length of output: 42


Script:

#!/bin/bash
# Let's try a different approach to find usages of delaySettings
rg -A 2 "delaySettings" 

# Also search for the Delay class implementation
fd "Delay.java" --exec cat {}

Length of output: 2709

}

public void unmarkDelay(T key) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.Duration;

@Deprecated
public interface DelaySettings {

Duration delay();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.eternalcode.core.feature.randomteleport;

public interface RandomTeleportRadius {
int maxZ();
int minZ();
int maxX();
int minX();

static RandomTeleportRadius of(int minX, int maxX, int minZ, int maxZ) {
return new SimpleRandomTeleportRadius(minX, maxX, minZ, maxZ);
}

static RandomTeleportRadius of(int radius) {
return new SimpleRandomTeleportRadius(-radius, radius, -radius, radius);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

import org.bukkit.Location;

public record TeleportResult(boolean success, Location location) {
public record RandomTeleportResult(boolean success, Location location) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public interface RandomTeleportService {
* @param player The player to teleport.
* @return A CompletableFuture containing the TeleportResult indicating the success or failure of the teleportation.
*/
CompletableFuture<TeleportResult> teleport(Player player);
CompletableFuture<RandomTeleportResult> teleport(Player player);

/**
* Asynchronously teleports the specified player to a random location within the specified world.
Expand All @@ -23,7 +23,7 @@ public interface RandomTeleportService {
* @param world The world to which the player should be teleported.
* @return A CompletableFuture containing the TeleportResult indicating the success or failure of the teleportation.
*/
CompletableFuture<TeleportResult> teleport(Player player, World world);
CompletableFuture<RandomTeleportResult> teleport(Player player, World world);

/**
* Asynchronously retrieves a safe random location within the specified world.
Expand All @@ -45,6 +45,16 @@ public interface RandomTeleportService {
*/
CompletableFuture<Location> getSafeRandomLocation(World world, int radius, int attemptCount);

/**
* Asynchronously retrieves a safe random location within the specified world, using radius.
*
* @param world The world in which to find a random location.
* @param radius The radius around the player to search for a safe location.
* @param attemptCount The number of attempts to find a safe location.
* @return A CompletableFuture containing the random Location that is deemed safe.
*/
CompletableFuture<Location> getSafeRandomLocation(World world, RandomTeleportRadius radius, int attemptCount);

/**
* Asynchronously retrieves a safe random location within the border in specified world.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.eternalcode.core.feature.randomteleport;

record SimpleRandomTeleportRadius(int minX, int maxX, int minZ, int maxZ) implements RandomTeleportRadius {
public SimpleRandomTeleportRadius {
if (minX > maxX) {
throw new IllegalArgumentException("minX cannot be greater than maxX");
}
if (minZ > maxZ) {
throw new IllegalArgumentException("minZ cannot be greater than maxZ");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.eternalcode.multification.notice.resolver.NoticeResolverRegistry;
import java.io.File;
import java.time.Duration;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.dzikoysk.cdn.Cdn;
Expand Down Expand Up @@ -77,4 +78,9 @@ public void reload() {
this.load(config);
}
}

public Set<ReloadableConfig> getConfigs() {
return Collections.unmodifiableSet(this.configs);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
import com.eternalcode.core.feature.automessage.AutoMessageSettings;
import com.eternalcode.core.feature.chat.ChatSettings;
import com.eternalcode.core.feature.jail.JailSettings;
import com.eternalcode.core.feature.randomteleport.RandomTeleportSettings;
import com.eternalcode.core.feature.randomteleport.RandomTeleportType;
import com.eternalcode.core.feature.helpop.HelpOpSettings;
import com.eternalcode.core.feature.randomteleport.RandomTeleportSettingsImpl;
import com.eternalcode.core.feature.spawn.SpawnSettings;
import com.eternalcode.core.injector.annotations.component.ConfigurationFile;
import com.eternalcode.core.feature.teleportrequest.TeleportRequestSettings;
Expand Down Expand Up @@ -125,58 +124,7 @@ public Duration teleportationTimeToSpawn() {
}

@Description({ "", "# Random Teleport Section" })
public RandomTeleport randomTeleport = new RandomTeleport();

@Contextual
public static class RandomTeleport implements RandomTeleportSettings, DelaySettings {
@Description({
"# Type of random teleportation,",
"# WORLD_BORDER_RADIUS - radius based on the world-border size.",
"# STATIC_RADIUS - radius based on the manually value."
})
public RandomTeleportType randomTeleportType = RandomTeleportType.WORLD_BORDER_RADIUS;

@Description({
"# Radius of random teleportation, this uses for starting point spawn via /setworldspawn.",
"# If you want to use a static radius, set the type to STATIC_RADIUS and set the radius here.",
"# If you using WORLD_BORDER_RADIUS, this value will be ignored."
})
public int randomTeleportRadius = 1000;

@Description("# Teleport to a specific world, if left empty it will teleport to the player's current world")
public String randomTeleportWorld = "world";

@Description("# Number of attempts to teleport to a random location")
public int randomTeleportAttempts = 10;

@Override
public int randomTeleportRadius() {
return this.randomTeleportRadius;
}

@Override
public RandomTeleportType randomTeleportType() {
return this.randomTeleportType;
}

@Override
public String randomTeleportWorld() {
return this.randomTeleportWorld;
}

@Override
public int randomTeleportAttempts() {
return this.randomTeleportAttempts;
}

@Description("# Delay to request next random teleportation")
public Duration randomTeleportDelay = Duration.ofSeconds(60);

@Override
public Duration delay() {
return this.randomTeleportDelay;
}
}
public RandomTeleportSettingsImpl randomTeleport = new RandomTeleportSettingsImpl();

@Description({ " ", "# Homes Section" })
public Homes homes = new Homes();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.eternalcode.core.configuration.migration;

public interface Migration {

boolean migrate();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.eternalcode.core.configuration.migration;

import com.eternalcode.core.configuration.ConfigurationManager;
import com.eternalcode.core.configuration.ReloadableConfig;
import com.eternalcode.core.injector.annotations.Inject;
import com.eternalcode.core.injector.annotations.component.Controller;
import com.eternalcode.core.publish.Subscribe;
import com.eternalcode.core.publish.Subscriber;
import com.eternalcode.core.publish.event.EternalInitializeEvent;
import java.util.logging.Logger;

@Controller
class MigrationController implements Subscriber {

private final MigrationService migrationService;
private final ConfigurationManager configurationManager;
private final Logger logger;

@Inject
MigrationController(MigrationService migrationService, ConfigurationManager configurationManager, Logger logger) {
this.migrationService = migrationService;
this.configurationManager = configurationManager;
this.logger = logger;
}
Comment on lines +19 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null checks for injected dependencies.

To prevent potential NullPointerExceptions, consider adding null validation in the constructor.

@Inject
MigrationController(MigrationService migrationService, ConfigurationManager configurationManager, Logger logger) {
+    if (migrationService == null || configurationManager == null || logger == null) {
+        throw new IllegalArgumentException("Dependencies cannot be null");
+    }
    this.migrationService = migrationService;
    this.configurationManager = configurationManager;
    this.logger = logger;
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Inject
MigrationController(MigrationService migrationService, ConfigurationManager configurationManager, Logger logger) {
this.migrationService = migrationService;
this.configurationManager = configurationManager;
this.logger = logger;
}
@Inject
MigrationController(MigrationService migrationService, ConfigurationManager configurationManager, Logger logger) {
if (migrationService == null || configurationManager == null || logger == null) {
throw new IllegalArgumentException("Dependencies cannot be null");
}
this.migrationService = migrationService;
this.configurationManager = configurationManager;
this.logger = logger;
}


@Subscribe
void onMigration(EternalInitializeEvent event) {
for (ReloadableConfig config : configurationManager.getConfigs()) {
boolean wasMigrated = migrationService.migrate(config);

if (wasMigrated) {
configurationManager.save(config);
logger.info("Configuration " + config.getClass().getSimpleName() + " was migrated and saved.");
}
}
}
Comment on lines +26 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance error handling and logging implementation.

The current implementation has several areas for improvement:

  1. Missing error handling for failed migrations
  2. Inefficient string concatenation in logging
  3. No progress tracking for multiple configurations

Consider implementing this enhanced version:

@Subscribe
void onMigration(EternalInitializeEvent event) {
+    int totalConfigs = configurationManager.getConfigs().size();
+    int migratedCount = 0;
    for (ReloadableConfig config : configurationManager.getConfigs()) {
+        String configName = config.getClass().getSimpleName();
+        try {
            boolean wasMigrated = migrationService.migrate(config);
            if (wasMigrated) {
                configurationManager.save(config);
-                logger.info("Configuration " + config.getClass().getSimpleName() + " was migrated and saved.");
+                logger.info(String.format("Configuration '%s' was migrated and saved successfully", configName));
+                migratedCount++;
            }
+        } catch (Exception e) {
+            logger.severe(String.format("Failed to migrate configuration '%s': %s", configName, e.getMessage()));
+        }
    }
+    logger.info(String.format("Migration completed: %d/%d configurations processed", migratedCount, totalConfigs));
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Subscribe
void onMigration(EternalInitializeEvent event) {
for (ReloadableConfig config : configurationManager.getConfigs()) {
boolean wasMigrated = migrationService.migrate(config);
if (wasMigrated) {
configurationManager.save(config);
logger.info("Configuration " + config.getClass().getSimpleName() + " was migrated and saved.");
}
}
}
@Subscribe
void onMigration(EternalInitializeEvent event) {
int totalConfigs = configurationManager.getConfigs().size();
int migratedCount = 0;
for (ReloadableConfig config : configurationManager.getConfigs()) {
String configName = config.getClass().getSimpleName();
try {
boolean wasMigrated = migrationService.migrate(config);
if (wasMigrated) {
configurationManager.save(config);
logger.info(String.format("Configuration '%s' was migrated and saved successfully", configName));
migratedCount++;
}
} catch (Exception e) {
logger.severe(String.format("Failed to migrate configuration '%s': %s", configName, e.getMessage()));
}
}
logger.info(String.format("Migration completed: %d/%d configurations processed", migratedCount, totalConfigs));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.eternalcode.core.configuration.migration;

import com.eternalcode.core.configuration.ReloadableConfig;
import com.eternalcode.core.injector.annotations.component.Service;
import com.eternalcode.core.util.ReflectUtil;
import java.lang.reflect.Field;
import net.dzikoysk.cdn.entity.Contextual;

@Service
class MigrationService {

public <T extends ReloadableConfig> boolean migrate(T config) {
return reflectMigrate(config);
}

private <T> boolean reflectMigrate(T config) {
boolean isMigrated = false;

for (Field declaredField : ReflectUtil.getAllSuperFields(config.getClass())) {
Class<?> fieldType = declaredField.getType();

if (Migration.class.isAssignableFrom(fieldType)) {
Migration migration = ReflectUtil.getFieldValue(declaredField, config);
boolean wasMigrationSuccessful = migration.migrate();
isMigrated |= wasMigrationSuccessful;
}
Comment on lines +22 to +26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential NullPointerException when migrating fields

If a field implementing Migration is null, invoking migration.migrate() will result in a NullPointerException. It's important to check if migration is not null before calling the migrate() method to prevent runtime exceptions.

Apply this fix to handle the null check:

if (Migration.class.isAssignableFrom(fieldType)) {
    Migration migration = ReflectUtil.getFieldValue(declaredField, config);
+   if (migration != null) {
        boolean wasMigrationSuccessful = migration.migrate();
        isMigrated |= wasMigrationSuccessful;
+   }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (Migration.class.isAssignableFrom(fieldType)) {
Migration migration = ReflectUtil.getFieldValue(declaredField, config);
boolean wasMigrationSuccessful = migration.migrate();
isMigrated |= wasMigrationSuccessful;
}
if (Migration.class.isAssignableFrom(fieldType)) {
Migration migration = ReflectUtil.getFieldValue(declaredField, config);
if (migration != null) {
boolean wasMigrationSuccessful = migration.migrate();
isMigrated |= wasMigrationSuccessful;
}
}


if (fieldType.isAnnotationPresent(Contextual.class)) {
Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
isMigrated |= reflectMigrate(fieldValue);
}
Comment on lines +28 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the annotation check for @Contextual on fields

Currently, the code checks if the field's type is annotated with @Contextual using fieldType.isAnnotationPresent(Contextual.class). If the intention is to check whether the field itself is annotated with @Contextual, the correct method is declaredField.isAnnotationPresent(Contextual.class).

Apply this fix to ensure the annotation check is performed on the field:

- if (fieldType.isAnnotationPresent(Contextual.class)) {
+ if (declaredField.isAnnotationPresent(Contextual.class)) {
    Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
+   if (fieldValue != null) {
        isMigrated |= reflectMigrate(fieldValue);
+   }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (fieldType.isAnnotationPresent(Contextual.class)) {
Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
isMigrated |= reflectMigrate(fieldValue);
}
if (declaredField.isAnnotationPresent(Contextual.class)) {
Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
if (fieldValue != null) {
isMigrated |= reflectMigrate(fieldValue);
}
}

Comment on lines +29 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Handle potential NullPointerException when migrating contextual fields

When accessing the value of a field annotated with @Contextual, the fieldValue might be null. Calling reflectMigrate(fieldValue) without checking can lead to a NullPointerException. Ensure that fieldValue is not null before recursively calling the migration method.

Apply this fix to handle the null check:

if (declaredField.isAnnotationPresent(Contextual.class)) {
    Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
+   if (fieldValue != null) {
        isMigrated |= reflectMigrate(fieldValue);
+   }
}

Committable suggestion skipped: line range outside the PR's diff.

}

return isMigrated;
}
Comment on lines +16 to +35
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider exception handling for reflective operations

Reflective operations such as getFieldValue can throw exceptions (e.g., IllegalAccessException, IllegalArgumentException). It's advisable to handle these exceptions to prevent unexpected crashes and to provide meaningful error messages.

Wrap the reflective calls in try-catch blocks and handle exceptions appropriately:

for (Field declaredField : ReflectUtil.getAllSuperFields(config.getClass())) {
    Class<?> fieldType = declaredField.getType();

    if (Migration.class.isAssignableFrom(fieldType)) {
+       try {
            Migration migration = ReflectUtil.getFieldValue(declaredField, config);
            if (migration != null) {
                boolean wasMigrationSuccessful = migration.migrate();
                isMigrated |= wasMigrationSuccessful;
            }
+       } catch (Exception e) {
+           // Handle exception or log error
+       }
    }

    if (declaredField.isAnnotationPresent(Contextual.class)) {
        try {
            Object fieldValue = ReflectUtil.getFieldValue(declaredField, config);
            if (fieldValue != null) {
                isMigrated |= reflectMigrate(fieldValue);
            }
        } catch (Exception e) {
            // Handle exception or log error
        }
    }
}

Committable suggestion skipped: line range outside the PR's diff.


}
Loading
Loading