Skip to content

Commit fe13591

Browse files
test(java): Add PMD static code analysis for Java files (#4183)
1 parent 8ae23a7 commit fe13591

File tree

19 files changed

+142
-64
lines changed

19 files changed

+142
-64
lines changed

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
"test": "lerna run test",
1010
"fix": "run-s fix:lerna fix:android",
1111
"fix:lerna": "lerna run fix",
12-
"fix:android": "./scripts/google-java-format.sh fix",
12+
"fix:android": "run-s 'java:format fix' java:pmd",
1313
"lint": "run-s lint:lerna lint:android",
1414
"lint:lerna": "lerna run lint",
15-
"lint:android": "./scripts/google-java-format.sh lint",
15+
"lint:android": "run-s 'java:format lint' java:pmd",
16+
"java:format": "./scripts/google-java-format.sh",
17+
"java:pmd": "./scripts/pmd.sh",
1618
"run-ios": "cd samples/react-native && yarn react-native run-ios",
1719
"run-android": "cd samples/react-native && yarn react-native run-android",
1820
"set-version-samples": "lerna run set-version"
@@ -23,6 +25,7 @@
2325
"google-java-format": "^1.4.0",
2426
"lerna": "^8.1.8",
2527
"npm-run-all2": "^6.2.2",
28+
"pmd-bin": "^2.5.0",
2629
"prettier": "^2.0.5",
2730
"react-native-version": "^4.0.0",
2831
"replace-in-file": "^7.0.1"

packages/core/android/src/main/java/io/sentry/react/RNSentryBreadcrumb.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
import org.jetbrains.annotations.NotNull;
88
import org.jetbrains.annotations.Nullable;
99

10-
public class RNSentryBreadcrumb {
10+
public final class RNSentryBreadcrumb {
11+
12+
private RNSentryBreadcrumb() {
13+
throw new AssertionError("Utility class should not be instantiated");
14+
}
1115

1216
@Nullable
1317
public static String getCurrentScreenFrom(ReadableMap from) {
1418
final @Nullable String maybeCategory =
1519
from.hasKey("category") ? from.getString("category") : null;
16-
if (maybeCategory == null || !maybeCategory.equals("navigation")) {
20+
if (maybeCategory == null || !"navigation".equals(maybeCategory)) {
1721
return null;
1822
}
1923

@@ -26,7 +30,7 @@ public static String getCurrentScreenFrom(ReadableMap from) {
2630
// getString might throw if cast to string fails (data.to is not enforced by TS to be a
2731
// string)
2832
return maybeData.hasKey("to") ? maybeData.getString("to") : null;
29-
} catch (Throwable exception) {
33+
} catch (Throwable exception) { // NOPMD - We don't want to crash in any case
3034
return null;
3135
}
3236
}

packages/core/android/src/main/java/io/sentry/react/RNSentryMapConverter.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@
1414
import java.util.Map;
1515
import org.jetbrains.annotations.Nullable;
1616

17-
public class RNSentryMapConverter {
17+
public final class RNSentryMapConverter {
1818
public static final String NAME = "RNSentry.MapConverter";
1919

2020
private static final ILogger logger = new AndroidLogger(NAME);
2121

22+
private RNSentryMapConverter() {
23+
throw new AssertionError("Utility class should not be instantiated");
24+
}
25+
2226
public static Object convertToWritable(@Nullable Object serialized) {
2327
if (serialized instanceof List) {
2428
WritableArray writable = Arguments.createArray();

packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public class RNSentryModuleImpl {
9191
private static final ILogger logger = new AndroidLogger(NAME);
9292
private static final BuildInfoProvider buildInfo = new BuildInfoProvider(logger);
9393
private static final String modulesPath = "modules.json";
94-
private static final Charset UTF_8 = Charset.forName("UTF-8");
94+
private static final Charset UTF_8 = Charset.forName("UTF-8"); // NOPMD - Allow using UTF-8
9595

9696
private final ReactApplicationContext reactApplicationContext;
9797
private final PackageInfo packageInfo;
@@ -270,7 +270,7 @@ public void initNativeSdk(final ReadableMap rnOptions, Promise promise) {
270270
if (null != ex && ex.getType().contains("JavascriptException")) {
271271
return null;
272272
}
273-
} catch (Throwable ignored) {
273+
} catch (Throwable ignored) { // NOPMD - We don't want to crash in any case
274274
// We do nothing
275275
}
276276

@@ -356,30 +356,29 @@ public void crash() {
356356
throw new RuntimeException("TEST - Sentry Client Crash (only works in release mode)");
357357
}
358358

359-
public void addListener(String _eventType) {
359+
public void addListener(String eventType) {
360360
// Is must be defined otherwise the generated interface from TS won't be fulfilled
361361
logger.log(SentryLevel.ERROR, "addListener of NativeEventEmitter can't be used on Android!");
362362
}
363363

364-
public void removeListeners(double _id) {
364+
public void removeListeners(double id) {
365365
// Is must be defined otherwise the generated interface from TS won't be fulfilled
366366
logger.log(
367367
SentryLevel.ERROR, "removeListeners of NativeEventEmitter can't be used on Android!");
368368
}
369369

370370
public void fetchModules(Promise promise) {
371371
final AssetManager assets = this.getReactApplicationContext().getResources().getAssets();
372-
try (final InputStream stream =
373-
new BufferedInputStream(assets.open(RNSentryModuleImpl.modulesPath))) {
372+
try (InputStream stream = new BufferedInputStream(assets.open(modulesPath))) {
374373
int size = stream.available();
375374
byte[] buffer = new byte[size];
376375
stream.read(buffer);
377376
stream.close();
378-
String modulesJson = new String(buffer, RNSentryModuleImpl.UTF_8);
377+
String modulesJson = new String(buffer, UTF_8);
379378
promise.resolve(modulesJson);
380379
} catch (FileNotFoundException e) {
381380
promise.resolve(null);
382-
} catch (Throwable e) {
381+
} catch (Throwable e) { // NOPMD - We don't want to crash in any case
383382
logger.log(SentryLevel.WARNING, "Fetching JS Modules failed.");
384383
promise.resolve(null);
385384
}
@@ -462,7 +461,7 @@ public void fetchNativeFrames(Promise promise) {
462461
map.putInt("frozenFrames", frozenFrames);
463462

464463
promise.resolve(map);
465-
} catch (Throwable ignored) {
464+
} catch (Throwable ignored) { // NOPMD - We don't want to crash in any case
466465
logger.log(SentryLevel.WARNING, "Error fetching native frames.");
467466
promise.resolve(null);
468467
}
@@ -493,7 +492,7 @@ public void captureEnvelope(String rawBytes, ReadableMap options, Promise promis
493492
try {
494493
InternalSentrySdk.captureEnvelope(
495494
bytes, !options.hasKey("hardCrashed") || !options.getBoolean("hardCrashed"));
496-
} catch (Throwable e) {
495+
} catch (Throwable e) { // NOPMD - We don't want to crash in any case
497496
logger.log(SentryLevel.ERROR, "Error while capturing envelope");
498497
promise.resolve(false);
499498
}
@@ -511,7 +510,7 @@ public void captureScreenshot(Promise promise) {
511510

512511
final byte[] raw = takeScreenshotOnUiThread(activity);
513512

514-
if (raw == null) {
513+
if (raw == null || raw.length == 0) {
515514
logger.log(SentryLevel.WARNING, "Screenshot is null, screen was not captured.");
516515
promise.resolve(null);
517516
return;
@@ -550,7 +549,7 @@ private static byte[] takeScreenshotOnUiThread(Activity activity) {
550549
doneSignal.await(SCREENSHOT_TIMEOUT_SECONDS, SECONDS);
551550
} catch (InterruptedException e) {
552551
logger.log(SentryLevel.ERROR, "Screenshot process was interrupted.");
553-
return null;
552+
return new byte[0];
554553
}
555554

556555
return bytesWrapper[0];
@@ -627,7 +626,7 @@ public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys)
627626
}
628627

629628
if (userDataKeys != null) {
630-
HashMap<String, String> userDataMap = new HashMap<>();
629+
Map<String, String> userDataMap = new HashMap<>();
631630
ReadableMapKeySetIterator it = userDataKeys.keySetIterator();
632631
while (it.hasNextKey()) {
633632
String key = it.nextKey();
@@ -694,7 +693,7 @@ public void setContext(final String key, final ReadableMap context) {
694693
return;
695694
}
696695

697-
final HashMap<String, Object> contextHashMap = context.toHashMap();
696+
final Map<String, Object> contextHashMap = context.toHashMap();
698697
scope.setContexts(key, contextHashMap);
699698
});
700699
}
@@ -726,7 +725,7 @@ public void enableNativeFramesTracking() {
726725
frameMetricsAggregator.add(currentActivity);
727726

728727
logger.log(SentryLevel.INFO, "FrameMetricsAggregator installed.");
729-
} catch (Throwable ignored) {
728+
} catch (Throwable ignored) { // NOPMD - We don't want to crash in any case
730729
// throws ConcurrentModification when calling addOnFrameMetricsAvailableListener
731730
// this is a best effort since we can't reproduce it
732731
logger.log(SentryLevel.ERROR, "Error adding Activity to frameMetricsAggregator.");
@@ -785,7 +784,7 @@ public WritableMap startProfiling(boolean platformProfilers) {
785784
}
786785

787786
result.putBoolean("started", true);
788-
} catch (Throwable e) {
787+
} catch (Throwable e) { // NOPMD - We don't want to crash in any case
789788
result.putBoolean("started", false);
790789
result.putString("error", e.toString());
791790
}
@@ -825,7 +824,7 @@ public WritableMap stopProfiling() {
825824
androidProfile.putString("build_id", getProguardUuid());
826825
result.putMap("androidProfile", androidProfile);
827826
}
828-
} catch (Throwable e) {
827+
} catch (Throwable e) { // NOPMD - We don't want to crash in any case
829828
result.putString("error", e.toString());
830829
} finally {
831830
if (output != null) {
@@ -834,7 +833,7 @@ public WritableMap stopProfiling() {
834833
if (!wasProfileSuccessfullyDeleted) {
835834
logger.log(SentryLevel.WARNING, "Profile not deleted from:" + output.getAbsolutePath());
836835
}
837-
} catch (Throwable e) {
836+
} catch (Throwable e) { // NOPMD - We don't want to crash in any case
838837
logger.log(SentryLevel.WARNING, "Profile not deleted from:" + output.getAbsolutePath());
839838
}
840839
}
@@ -848,7 +847,7 @@ public WritableMap stopProfiling() {
848847
}
849848
isProguardDebugMetaLoaded = true;
850849
final @Nullable List<Properties> debugMetaList =
851-
(new AssetsDebugMetaLoader(this.getReactApplicationContext(), logger)).loadDebugMeta();
850+
new AssetsDebugMetaLoader(this.getReactApplicationContext(), logger).loadDebugMeta();
852851
if (debugMetaList == null) {
853852
return null;
854853
}
@@ -866,7 +865,7 @@ public WritableMap stopProfiling() {
866865
}
867866

868867
private String readStringFromFile(File path) throws IOException {
869-
try (final BufferedReader br = new BufferedReader(new FileReader(path)); ) {
868+
try (BufferedReader br = new BufferedReader(new FileReader(path)); ) {
870869

871870
final StringBuilder text = new StringBuilder();
872871
String line;
@@ -943,7 +942,7 @@ private void setEventEnvironmentTag(SentryEvent event, String environment) {
943942
private void addPackages(SentryEvent event, SdkVersion sdk) {
944943
SdkVersion eventSdk = event.getSdk();
945944
if (eventSdk != null
946-
&& eventSdk.getName().equals("sentry.javascript.react-native")
945+
&& "sentry.javascript.react-native".equals(eventSdk.getName())
947946
&& sdk != null) {
948947
List<SentryPackage> sentryPackages = sdk.getPackages();
949948
if (sentryPackages != null) {

packages/core/android/src/main/java/io/sentry/react/RNSentryReactFragmentLifecycleTracer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public void onFragmentViewCreated(
4040
@NotNull Fragment f,
4141
@NotNull View v,
4242
@Nullable Bundle savedInstanceState) {
43-
if (!("com.swmansion.rnscreens.ScreenStackFragment".equals(f.getClass().getCanonicalName()))) {
43+
if (!"com.swmansion.rnscreens.ScreenStackFragment".equals(f.getClass().getCanonicalName())) {
4444
logger.log(
4545
SentryLevel.DEBUG,
4646
"Fragment is not a ScreenStackFragment, won't listen for the first draw.");

packages/core/android/src/main/java/io/sentry/react/RNSentryReplayBreadcrumbConverter.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,29 @@
1313
import org.jetbrains.annotations.TestOnly;
1414

1515
public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadcrumbConverter {
16-
public RNSentryReplayBreadcrumbConverter() {}
17-
1816
@Override
1917
public @Nullable RRWebEvent convert(final @NotNull Breadcrumb breadcrumb) {
2018
if (breadcrumb.getCategory() == null) {
2119
return null;
2220
}
2321

2422
// Do not add Sentry Event breadcrumbs to replay
25-
if (breadcrumb.getCategory().equals("sentry.event")
26-
|| breadcrumb.getCategory().equals("sentry.transaction")) {
23+
if ("sentry.event".equals(breadcrumb.getCategory())
24+
|| "sentry.transaction".equals(breadcrumb.getCategory())) {
2725
return null;
2826
}
29-
if (breadcrumb.getCategory().equals("http")) {
27+
if ("http".equals(breadcrumb.getCategory())) {
3028
// Drop native http breadcrumbs to avoid duplicates
3129
return null;
3230
}
3331

34-
if (breadcrumb.getCategory().equals("touch")) {
32+
if ("touch".equals(breadcrumb.getCategory())) {
3533
return convertTouchBreadcrumb(breadcrumb);
3634
}
37-
if (breadcrumb.getCategory().equals("navigation")) {
35+
if ("navigation".equals(breadcrumb.getCategory())) {
3836
return convertNavigationBreadcrumb(breadcrumb);
3937
}
40-
if (breadcrumb.getCategory().equals("xhr")) {
38+
if ("xhr".equals(breadcrumb.getCategory())) {
4139
return convertNetworkBreadcrumb(breadcrumb);
4240
}
4341

@@ -46,8 +44,7 @@ public RNSentryReplayBreadcrumbConverter() {}
4644
// ignore native navigation breadcrumbs
4745
if (nativeBreadcrumb instanceof RRWebBreadcrumbEvent) {
4846
final RRWebBreadcrumbEvent rrWebBreadcrumb = (RRWebBreadcrumbEvent) nativeBreadcrumb;
49-
if (rrWebBreadcrumb.getCategory() != null
50-
&& rrWebBreadcrumb.getCategory().equals("navigation")) {
47+
if ("navigation".equals(rrWebBreadcrumb.getCategory())) {
5148
return null;
5249
}
5350
}
@@ -69,8 +66,7 @@ public RNSentryReplayBreadcrumbConverter() {}
6966

7067
rrWebBreadcrumb.setCategory("ui.tap");
7168

72-
rrWebBreadcrumb.setMessage(
73-
RNSentryReplayBreadcrumbConverter.getTouchPathMessage(breadcrumb.getData("path")));
69+
rrWebBreadcrumb.setMessage(getTouchPathMessage(breadcrumb.getData("path")));
7470

7571
setRRWebEventDefaultsFrom(rrWebBreadcrumb, breadcrumb);
7672
return rrWebBreadcrumb;
@@ -83,7 +79,7 @@ public RNSentryReplayBreadcrumbConverter() {}
8379
}
8480

8581
final @NotNull List path = (List) maybePath;
86-
if (path.size() == 0) {
82+
if (path.isEmpty()) {
8783
return null;
8884
}
8985

@@ -145,7 +141,7 @@ public RNSentryReplayBreadcrumbConverter() {}
145141
return null;
146142
}
147143

148-
final HashMap<String, Object> data = new HashMap<>();
144+
final Map<String, Object> data = new HashMap<>();
149145
if (breadcrumb.getData("method") instanceof String) {
150146
data.put("method", breadcrumb.getData("method"));
151147
}

performance-tests/TestAppPlain/android/app/src/debug/java/com/testappplain/ReactNativeFlipper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import com.facebook.react.modules.network.NetworkingModule;
2626
import okhttp3.OkHttpClient;
2727

28-
public class ReactNativeFlipper {
28+
public class ReactNativeFlipper { // NOPMD - Default RN Template
2929
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
3030
if (FlipperUtils.shouldEnableFlipper(context)) {
3131
final FlipperClient client = AndroidFlipperClient.getInstance(context);

performance-tests/TestAppPlain/android/app/src/main/java/com/testappplain/MainApplication.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public void onCreate() {
6565
* @param context
6666
* @param reactInstanceManager
6767
*/
68-
private static void initializeFlipper(
68+
private static void initializeFlipper( // NOPMD - Default RN Template
6969
Context context, ReactInstanceManager reactInstanceManager) {
7070
if (BuildConfig.DEBUG) {
7171
try {
@@ -79,11 +79,11 @@ private static void initializeFlipper(
7979
.invoke(null, context, reactInstanceManager);
8080
} catch (ClassNotFoundException e) {
8181
e.printStackTrace();
82-
} catch (NoSuchMethodException e) {
82+
} catch (NoSuchMethodException e) { // NOPMD - Default RN Template
8383
e.printStackTrace();
84-
} catch (IllegalAccessException e) {
84+
} catch (IllegalAccessException e) { // NOPMD - Default RN Template
8585
e.printStackTrace();
86-
} catch (InvocationTargetException e) {
86+
} catch (InvocationTargetException e) { // NOPMD - Default RN Template
8787
e.printStackTrace();
8888
}
8989
}

performance-tests/TestAppPlain/android/app/src/main/java/com/testappplain/newarchitecture/MainApplicationReactNativeHost.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ public boolean getUseDeveloperSupport() {
4444

4545
@Override
4646
protected List<ReactPackage> getPackages() {
47-
List<ReactPackage> packages = new PackageList(this).getPackages();
47+
List<ReactPackage> packages = // NOPMD - Default RN Template
48+
new PackageList(this).getPackages();
4849
// Packages that cannot be autolinked yet can be added manually here, for example:
4950
// packages.add(new MyReactNativePackage());
5051
// TurboModules must also be loaded here providing a valid TurboReactPackage implementation:

performance-tests/TestAppPlain/android/app/src/main/java/com/testappplain/newarchitecture/components/MainComponentsRegistry.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* `newArchEnabled` property). Is ignored otherwise.
1515
*/
1616
@DoNotStrip
17-
public class MainComponentsRegistry {
17+
public class MainComponentsRegistry { // NOPMD - Default RN Template
1818
static {
1919
SoLoader.loadLibrary("fabricjni");
2020
}

0 commit comments

Comments
 (0)