• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

raphw / byte-buddy / #809

02 Nov 2025 10:24PM UTC coverage: 84.035% (-0.6%) from 84.614%
#809

push

raphw
Clean up code.

5 of 7 new or added lines in 4 files covered. (71.43%)

958 existing lines in 10 files now uncovered.

29803 of 35465 relevant lines covered (84.03%)

0.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

25.59
/byte-buddy-dep/src/main/java/net/bytebuddy/description/module/ModuleDescription.java
1
/*
2
 * Copyright 2014 - Present Rafael Winterhalter
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.bytebuddy.description.module;
17

18
import net.bytebuddy.build.AccessControllerPlugin;
19
import net.bytebuddy.description.ModifierReviewable;
20
import net.bytebuddy.description.NamedElement;
21
import net.bytebuddy.description.annotation.AnnotationDescription;
22
import net.bytebuddy.description.annotation.AnnotationList;
23
import net.bytebuddy.description.annotation.AnnotationSource;
24
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
25
import net.bytebuddy.utility.nullability.AlwaysNull;
26
import net.bytebuddy.utility.nullability.MaybeNull;
27
import org.objectweb.asm.ClassVisitor;
28
import org.objectweb.asm.ModuleVisitor;
29
import org.objectweb.asm.Opcodes;
30

31
import java.lang.reflect.AnnotatedElement;
32
import java.security.PrivilegedAction;
33
import java.util.Iterator;
34
import java.util.LinkedHashMap;
35
import java.util.LinkedHashSet;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Set;
39

40
/**
41
 * Description of a named Java {@code java.lang.Module}.
42
 */
43
public interface ModuleDescription extends NamedElement,
44
        ModifierReviewable.ForModuleDescription,
45
        AnnotationSource {
46

47
    /**
48
     * The name of a Java class representing a module description.
49
     */
50
    String MODULE_CLASS_NAME = "module-info";
51

52
    /**
53
     * Defines a module that is not resolved.
54
     */
55
    @AlwaysNull
56
    ModuleDescription UNDEFINED = null;
1✔
57

58
    /**
59
     * Writes this module description as meta data to the provided {@link ClassVisitor}.
60
     *
61
     * @param classVisitor The class visitor to write to.
62
     */
63
    void accept(ClassVisitor classVisitor);
64

65
    /**
66
     * Returns the version of this module.
67
     *
68
     * @return The module's version or {@code null} if no version is specified.
69
     */
70
    @MaybeNull
71
    String getVersion();
72

73
    /**
74
     * Returns the main class of this module.
75
     *
76
     * @return The module's main class or {@code null} if no main class is specified.
77
     */
78
    @MaybeNull
79
    String getMainClass();
80

81
    /**
82
     * Returns all packages contained in this module.
83
     *
84
     * @return A set of all package names within this module.
85
     */
86
    Set<String> getPackages();
87

88
    /**
89
     * Returns all package exports of this module.
90
     *
91
     * @return A mapping of package names to their export declarations.
92
     */
93
    Map<String, Exports> getExports();
94

95
    /**
96
     * Returns all package opens of this module.
97
     *
98
     * @return A mapping of package names to their opens declarations.
99
     */
100
    Map<String, Opens> getOpens();
101

102
    /**
103
     * Returns all module dependencies of this module.
104
     *
105
     * @return A mapping of module names to their require declarations.
106
     */
107
    Map<String, Requires> getRequires();
108

109
    /**
110
     * Returns all service types that this module uses.
111
     *
112
     * @return A set of service class names that this module uses.
113
     */
114
    Set<String> getUses();
115

116
    /**
117
     * Returns all service implementations provided by this module.
118
     *
119
     * @return A mapping of service names to their provider declarations.
120
     */
121
    Map<String, Provides> getProvides();
122

123
    /**
124
     * Represents an exported package declaration in a module. Exports control which packages
125
     * are accessible to other modules.
126
     */
127
    interface Exports extends ModifierReviewable.OfMandatable {
128

129
        /**
130
         * Returns the target modules that this package is exported to.
131
         *
132
         * @return A set of module names that can access this exported package, or an empty set if exported to all modules.
133
         */
134
        Set<String> getTargets();
135

136
        /**
137
         * Determines if this export is qualified (exported to specific modules only).
138
         *
139
         * @return {@code true} if this export has specific target modules, {@code false} if exported to all modules.
140
         */
141
        boolean isQualified();
142

143
        /**
144
         * An abstract base implementation of {@link Exports} that provides a default implementation
145
         * for {@link #isQualified()}.
146
         */
147
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Exports {
1✔
148

149
            /**
150
             * {@inheritDoc}
151
             */
152
            public boolean isQualified() {
UNCOV
153
                return !getTargets().isEmpty();
×
154
            }
155

156
            @Override
157
            public int hashCode() {
158
                int hashCode = getModifiers();
1✔
159
                return hashCode + 17 * getTargets().hashCode();
1✔
160
            }
161

162
            @Override
163
            public boolean equals(Object other) {
164
                if (!(other instanceof Exports)) return false;
1✔
165
                Exports exports = (Exports) other;
1✔
166
                return getModifiers() == exports.getModifiers() && getTargets().equals(exports.getTargets());
1✔
167
            }
168

169
            @Override
170
            public String toString() {
UNCOV
171
                return "Opens{"
×
UNCOV
172
                        + "targets=" + getTargets()
×
UNCOV
173
                        + ",modifiers=" + getModifiers()
×
174
                        + '}';
175
            }
176
        }
177

178
        /**
179
         * A simple implementation of {@link Exports} that stores the target modules and modifiers.
180
         */
181
        class Simple extends AbstractBase {
182

183
            /**
184
             * The target modules for this export.
185
             */
186
            private final Set<String> targets;
187

188
            /**
189
             * The modifiers for this export.
190
             */
191
            protected final int modifiers;
192

193
            /**
194
             * Creates a new simple export declaration.
195
             *
196
             * @param targets   The target modules for this export.
197
             * @param modifiers The modifiers for this export.
198
             */
199
            public Simple(Set<String> targets, int modifiers) {
1✔
200
                this.targets = targets;
1✔
201
                this.modifiers = modifiers;
1✔
202
            }
1✔
203

204
            /**
205
             * {@inheritDoc}
206
             */
207
            public Set<String> getTargets() {
208
                return targets;
1✔
209
            }
210

211
            /**
212
             * {@inheritDoc}
213
             */
214
            public int getModifiers() {
215
                return modifiers;
1✔
216
            }
217
        }
218
    }
219

220
    /**
221
     * Represents an opened package declaration in a module. Opens allow deep reflective access
222
     * to packages for other modules.
223
     */
224
    interface Opens extends ModifierReviewable.OfMandatable {
225

226
        /**
227
         * Returns the target modules that this package is opened to.
228
         *
229
         * @return A set of module names that can reflectively access this opened package, or an empty set if opened to all modules.
230
         */
231
        Set<String> getTargets();
232

233
        /**
234
         * Determines if this opens declaration is qualified (opened to specific modules only).
235
         *
236
         * @return {@code true} if this opens has specific target modules, {@code false} if opened to all modules.
237
         */
238
        boolean isQualified();
239

240
        /**
241
         * An abstract base implementation of {@link Opens}.
242
         */
243
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Opens {
1✔
244

245
            /**
246
             * {@inheritDoc}
247
             */
248
            public boolean isQualified() {
UNCOV
249
                return !getTargets().isEmpty();
×
250
            }
251

252
            @Override
253
            public int hashCode() {
254
                int hashCode = getModifiers();
1✔
255
                return hashCode + 17 * getTargets().hashCode();
1✔
256
            }
257

258
            @Override
259
            public boolean equals(Object other) {
260
                if (!(other instanceof Opens)) return false;
1✔
261
                Opens opens = (Opens) other;
1✔
262
                return getModifiers() == opens.getModifiers() && getTargets().equals(opens.getTargets());
1✔
263
            }
264

265
            @Override
266
            public String toString() {
UNCOV
267
                return "Opens{"
×
UNCOV
268
                        + "targets=" + getTargets()
×
UNCOV
269
                        + ",modifiers=" + getModifiers()
×
270
                        + '}';
271
            }
272
        }
273

274
        /**
275
         * A simple implementation of {@link Opens}.
276
         */
277
        class Simple extends AbstractBase {
278

279
            /**
280
             * The target modules for this opens declaration.
281
             */
282
            private final Set<String> targets;
283

284
            /**
285
             * The modifiers for this opens declaration.
286
             */
287
            protected final int modifiers;
288

289
            /**
290
             * Creates a new simple opens declaration.
291
             *
292
             * @param targets   The target modules for this opens declaration.
293
             * @param modifiers The modifiers for this opens declaration.
294
             */
295
            public Simple(Set<String> targets, int modifiers) {
1✔
296
                this.targets = targets;
1✔
297
                this.modifiers = modifiers;
1✔
298
            }
1✔
299

300
            /**
301
             * {@inheritDoc}
302
             */
303
            public Set<String> getTargets() {
304
                return targets;
1✔
305
            }
306

307
            /**
308
             * {@inheritDoc}
309
             */
310
            public int getModifiers() {
311
                return modifiers;
1✔
312
            }
313
        }
314
    }
315

316
    /**
317
     * Represents a module dependency declaration. Requires specify which modules this module
318
     * depends on for compilation and runtime.
319
     */
320
    interface Requires extends ModifierReviewable.ForModuleRequirement {
321

322
        /**
323
         * Returns the version of the required module.
324
         *
325
         * @return The required module's version or {@code null} if no specific version is required.
326
         */
327
        @MaybeNull
328
        String getVersion();
329

330
        /**
331
         * An abstract base implementation of {@link Requires}.
332
         */
333
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Requires {
1✔
334

335
            @Override
336
            public int hashCode() {
337
                int hashCode = getModifiers();
1✔
338
                String version = getVersion();
1✔
339
                return version == null ? hashCode : (hashCode + 17 * version.hashCode());
1✔
340
            }
341

342
            @Override
343
            public boolean equals(Object other) {
344
                if (!(other instanceof Requires)) return false;
1✔
345
                Requires requires = (Requires) other;
1✔
346
                String version = getVersion();
1✔
347
                return getModifiers() == requires.getModifiers() && version == null ? requires.getVersion() == null : version.equals(requires.getVersion());
1✔
348
            }
349

350
            @Override
351
            public String toString() {
UNCOV
352
                String version = getVersion();
×
UNCOV
353
                return "Requires{"
×
354
                        + "version=" + (version == null ? "" : '"' + version + '\'')
UNCOV
355
                        + ",modifiers=" + getModifiers()
×
356
                        + '}';
357
            }
358
        }
359

360
        /**
361
         * A simple implementation of {@link Requires}.
362
         */
363
        class Simple extends AbstractBase {
364

365
            /**
366
             * The version of the required module.
367
             */
368
            @MaybeNull
369
            private final String version;
370

371
            /**
372
             * The modifiers for this requires declaration.
373
             */
374
            private final int modifiers;
375

376
            /**
377
             * Creates a new simple requires declaration.
378
             *
379
             * @param version   The version of the required module or {@code null} if no specific version is required.
380
             * @param modifiers The modifiers for this requires declaration.
381
             */
382
            public Simple(@MaybeNull String version, int modifiers) {
1✔
383
                this.version = version;
1✔
384
                this.modifiers = modifiers;
1✔
385
            }
1✔
386

387
            /**
388
             * {@inheritDoc}
389
             */
390
            @MaybeNull
391
            public String getVersion() {
392
                return version;
1✔
393
            }
394

395
            /**
396
             * {@inheritDoc}
397
             */
398
            public int getModifiers() {
399
                return modifiers;
1✔
400
            }
401
        }
402
    }
403

404
    /**
405
     * Represents a service provider declaration in a module. Provides specify which service
406
     * implementations this module offers to other modules.
407
     */
408
    interface Provides {
409

410
        /**
411
         * Returns the implementation classes that provide the service.
412
         *
413
         * @return A set of class names that implement the service.
414
         */
415
        Set<String> getProviders();
416

417
        /**
418
         * An abstract base implementation of {@link Provides}.
419
         */
420
        abstract class AbstractBase implements Provides {
1✔
421

422
            @Override
423
            public int hashCode() {
424
                return getProviders().hashCode();
1✔
425
            }
426

427
            @Override
428
            public boolean equals(Object other) {
429
                if (!(other instanceof Provides)) return false;
1✔
430
                Provides provides = (Provides) other;
1✔
431
                return getProviders().equals(provides.getProviders());
1✔
432
            }
433

434
            @Override
435
            public String toString() {
UNCOV
436
                return "Provides{providers=" + getProviders() + '}';
×
437
            }
438
        }
439

440
        /**
441
         * A simple implementation of {@link Provides}.
442
         */
443
        class Simple extends AbstractBase {
444

445
            /**
446
             * The implementation classes that provide the service.
447
             */
448
            private final Set<String> providers;
449

450
            /**
451
             * Creates a new simple provides declaration.
452
             *
453
             * @param providers The implementation classes that provide the service.
454
             */
455
            public Simple(Set<String> providers) {
1✔
456
                this.providers = providers;
1✔
457
            }
1✔
458

459
            /**
460
             * {@inheritDoc}
461
             */
462
            public Set<String> getProviders() {
463
                return providers;
1✔
464
            }
465
        }
466
    }
467

468
    /**
469
     * An abstract base implementation of a {@link ModuleDescription}.
470
     */
471
    abstract class AbstractBase extends ModifierReviewable.AbstractBase implements ModuleDescription {
1✔
472

473
        /**
474
         * {@inheritDoc}
475
         */
476
        public void accept(ClassVisitor classVisitor) {
477
            ModuleVisitor moduleVisitor = classVisitor.visitModule(getActualName(), getModifiers(), getVersion());
×
478
            if (moduleVisitor != null) {
×
479
                String mainClass = getMainClass();
×
480
                if (mainClass != null) {
×
481
                    moduleVisitor.visitMainClass(mainClass.replace('.', '/'));
×
482
                }
483
                for (String aPackage : getPackages()) {
×
484
                    moduleVisitor.visitPackage(aPackage.replace('.', '/'));
×
485
                }
×
486
                for (Map.Entry<String, ModuleDescription.Requires> entry : getRequires().entrySet()) {
×
487
                    moduleVisitor.visitRequire(entry.getKey(), entry.getValue().getModifiers(), entry.getValue().getVersion());
×
488
                }
×
489
                for (Map.Entry<String, ModuleDescription.Exports> entry : getExports().entrySet()) {
×
490
                    moduleVisitor.visitExport(entry.getKey().replace('.', '/'),
×
491
                            entry.getValue().getModifiers(),
×
492
                            entry.getValue().getTargets().isEmpty() ? null : entry.getValue().getTargets().toArray(new String[0]));
×
493
                }
×
494
                for (Map.Entry<String, ModuleDescription.Opens> entry : getOpens().entrySet()) {
×
495
                    moduleVisitor.visitOpen(entry.getKey().replace('.', '/'),
×
496
                            entry.getValue().getModifiers(),
×
497
                            entry.getValue().getTargets().isEmpty() ? null : entry.getValue().getTargets().toArray(new String[0]));
×
498
                }
×
499
                for (String use : getUses()) {
×
500
                    moduleVisitor.visitUse(use.replace('.', '/'));
×
501
                }
×
UNCOV
502
                for (Map.Entry<String, ModuleDescription.Provides> entry : getProvides().entrySet()) {
×
UNCOV
503
                    String[] provider = entry.getValue().getProviders().isEmpty() ? null : new String[entry.getValue().getProviders().size()];
×
504
                    if (provider != null) {
×
505
                        Iterator<String> iterator = entry.getValue().getProviders().iterator();
×
506
                        for (int index = 0; index < provider.length; index++) {
×
UNCOV
507
                            provider[index] = iterator.next().replace('.', '/');
×
508
                        }
509
                    }
UNCOV
510
                    moduleVisitor.visitProvide(entry.getKey().replace('.', '/'), provider);
×
UNCOV
511
                }
×
UNCOV
512
                moduleVisitor.visitEnd();
×
513
            }
UNCOV
514
        }
×
515

516
        @Override
517
        public int hashCode() {
518
            return 17 * getActualName().hashCode();
1✔
519
        }
520

521
        @Override
522
        public boolean equals(Object other) {
523
            if (!(other instanceof ModuleDescription)) return false;
1✔
524
            ModuleDescription module = (ModuleDescription) other;
1✔
525
            return getActualName().equals(module.getActualName());
1✔
526
        }
527

528
        @Override
529
        public String toString() {
530
            return "module " + getActualName();
1✔
531
        }
532
    }
533

534
    /**
535
     * A {@link ModuleDescription} implementation that represents a loaded Java module.
536
     * This implementation uses reflection and Java dispatchers to access module information
537
     * from the runtime module system.
538
     */
539
    class ForLoadedModule extends AbstractBase {
540

541
        /**
542
         * A dispatcher for accessing {@code java.lang.Module} methods.
543
         */
UNCOV
544
        protected static final Module MODULE = doPrivileged(JavaDispatcher.of(Module.class));
×
545

546
        /**
547
         * A dispatcher for accessing {@code java.lang.ModuleDescriptor} methods.
548
         */
UNCOV
549
        protected static final ModuleDescriptor MODULE_DESCRIPTOR = doPrivileged(JavaDispatcher.of(ModuleDescriptor.class));
×
550

551
        /**
552
         * A dispatcher for accessing {@code java.lang.ModuleDescriptor.Exports} methods.
553
         */
UNCOV
554
        protected static final ModuleDescriptor.Exports MODULE_DESCRIPTOR_EXPORTS = doPrivileged(JavaDispatcher.of(ModuleDescriptor.Exports.class));
×
555

556
        /**
557
         * A dispatcher for accessing {@code java.lang.ModuleDescriptor.Opens} methods.
558
         */
UNCOV
559
        protected static final ModuleDescriptor.Opens MODULE_DESCRIPTOR_OPENS = doPrivileged(JavaDispatcher.of(ModuleDescriptor.Opens.class));
×
560

561
        /**
562
         * A dispatcher for accessing {@code java.lang.ModuleDescriptor.Requires} methods.
563
         */
UNCOV
564
        protected static final ModuleDescriptor.Requires MODULE_DESCRIPTOR_REQUIRES = doPrivileged(JavaDispatcher.of(ModuleDescriptor.Requires.class));
×
565

566
        /**
567
         * A dispatcher for accessing {@code java.lang.ModuleDescriptor.Provides} methods.
568
         */
UNCOV
569
        protected static final ModuleDescriptor.Provides MODULE_DESCRIPTOR_PROVIDES = doPrivileged(JavaDispatcher.of(ModuleDescriptor.Provides.class));
×
570

571
        /**
572
         * A dispatcher for accessing {@code java.util.Optional} methods.
573
         */
UNCOV
574
        protected static final Optional OPTIONAL = doPrivileged(JavaDispatcher.of(Optional.class));
×
575

576
        /**
577
         * The module represented by this description.
578
         */
579
        private final AnnotatedElement module;
580

581
        /**
582
         * Creates a module description for the supplied module.
583
         *
584
         * @param module The module to represent.
585
         * @return A module description for the supplied module.
586
         * @throws IllegalArgumentException If the supplied instance is not a module or if the module is unnamed.
587
         */
588
        public static ModuleDescription of(Object module) {
UNCOV
589
            if (!MODULE.isInstance(module)) {
×
UNCOV
590
                throw new IllegalArgumentException("Not a Java module: " + module);
×
UNCOV
591
            } else if (!MODULE.isNamed(module)) {
×
UNCOV
592
                throw new IllegalArgumentException("Not a named module: " + module);
×
593
            }
UNCOV
594
            return new ForLoadedModule((AnnotatedElement) module);
×
595
        }
596

597
        /**
598
         * A proxy for {@code java.security.AccessController#doPrivileged} that is activated if available.
599
         *
600
         * @param action The action to execute from a privileged context.
601
         * @param <T>    The type of the action's resolved value.
602
         * @return The action's resolved value.
603
         */
604
        @AccessControllerPlugin.Enhance
605
        private static <T> T doPrivileged(PrivilegedAction<T> action) {
UNCOV
606
            return action.run();
×
607
        }
608

609
        /**
610
         * Creates a new module description for the supplied module.
611
         *
612
         * @param module The module to represent.
613
         */
UNCOV
614
        protected ForLoadedModule(AnnotatedElement module) {
×
UNCOV
615
            this.module = module;
×
UNCOV
616
        }
×
617

618
        /**
619
         * {@inheritDoc}
620
         */
621
        @MaybeNull
622
        public String getVersion() {
UNCOV
623
            return (String) OPTIONAL.orElse(MODULE_DESCRIPTOR.rawVersion(MODULE.getDescriptor(module)), null);
×
624
        }
625

626
        /**
627
         * {@inheritDoc}
628
         */
629
        @MaybeNull
630
        public String getMainClass() {
UNCOV
631
            return (String) OPTIONAL.orElse(MODULE_DESCRIPTOR.mainClass(MODULE.getDescriptor(module)), null);
×
632
        }
633

634
        /**
635
         * {@inheritDoc}
636
         */
637
        public boolean isOpen() {
UNCOV
638
            return MODULE_DESCRIPTOR.isOpen(MODULE.getDescriptor(module));
×
639
        }
640

641
        /**
642
         * {@inheritDoc}
643
         */
644
        public Set<String> getPackages() {
UNCOV
645
            return MODULE_DESCRIPTOR.packages(MODULE.getDescriptor(module));
×
646
        }
647

648
        /**
649
         * {@inheritDoc}
650
         */
651
        public Set<String> getUses() {
UNCOV
652
            return MODULE_DESCRIPTOR.uses(MODULE.getDescriptor(module));
×
653
        }
654

655
        /**
656
         * {@inheritDoc}
657
         */
658
        public Map<String, Exports> getExports() {
659
            Map<String, Exports> exports = new LinkedHashMap<String, Exports>();
×
660
            for (Object export : MODULE_DESCRIPTOR.exports(MODULE.getDescriptor(module))) {
×
661
                int modifiers = 0;
×
UNCOV
662
                for (Enum<?> modifier : MODULE_DESCRIPTOR_EXPORTS.modifiers(export)) {
×
663
                    String name = modifier.name();
×
UNCOV
664
                    if (name.equals("SYNTHETIC")) {
×
665
                        modifiers |= Opcodes.ACC_SYNTHETIC;
×
666
                    } else if (name.equals("MANDATED")) {
×
667
                        modifiers |= Opcodes.ACC_MANDATED;
×
668
                    } else {
UNCOV
669
                        throw new IllegalStateException("Unknown export modifier: " + name);
×
670
                    }
UNCOV
671
                }
×
UNCOV
672
                exports.put(MODULE_DESCRIPTOR_EXPORTS.source(export), new Exports.Simple(MODULE_DESCRIPTOR_EXPORTS.targets(export), modifiers));
×
UNCOV
673
            }
×
UNCOV
674
            return exports;
×
675
        }
676

677
        /**
678
         * {@inheritDoc}
679
         */
680
        public Map<String, Opens> getOpens() {
681
            Map<String, Opens> opens = new LinkedHashMap<String, Opens>();
×
682
            for (Object open : MODULE_DESCRIPTOR.opens(MODULE.getDescriptor(module))) {
×
683
                int modifiers = 0;
×
UNCOV
684
                for (Enum<?> modifier : MODULE_DESCRIPTOR_OPENS.modifiers(open)) {
×
685
                    String name = modifier.name();
×
UNCOV
686
                    if (name.equals("SYNTHETIC")) {
×
687
                        modifiers |= Opcodes.ACC_SYNTHETIC;
×
688
                    } else if (name.equals("MANDATED")) {
×
689
                        modifiers |= Opcodes.ACC_MANDATED;
×
690
                    } else {
UNCOV
691
                        throw new IllegalStateException("Unknown opens modifier: " + name);
×
692
                    }
UNCOV
693
                }
×
UNCOV
694
                opens.put(MODULE_DESCRIPTOR_OPENS.source(open), new Opens.Simple(MODULE_DESCRIPTOR_OPENS.targets(open), modifiers));
×
UNCOV
695
            }
×
UNCOV
696
            return opens;
×
697
        }
698

699
        /**
700
         * {@inheritDoc}
701
         */
702
        public Map<String, Requires> getRequires() {
703
            Map<String, Requires> requires = new LinkedHashMap<String, Requires>();
×
704
            for (Object require : MODULE_DESCRIPTOR.requires(MODULE.getDescriptor(module))) {
×
705
                int modifiers = 0;
×
706
                for (Enum<?> modifier : MODULE_DESCRIPTOR_REQUIRES.modifiers(require)) {
×
707
                    String name = modifier.name();
×
708
                    if (name.equals("SYNTHETIC")) {
×
709
                        modifiers |= Opcodes.ACC_SYNTHETIC;
×
UNCOV
710
                    } else if (name.equals("MANDATED")) {
×
711
                        modifiers |= Opcodes.ACC_MANDATED;
×
UNCOV
712
                    } else if (name.equals("TRANSITIVE")) {
×
713
                        modifiers |= Opcodes.ACC_TRANSITIVE;
×
714
                    } else if (name.equals("STATIC")) {
×
715
                        modifiers |= Opcodes.ACC_STATIC_PHASE;
×
716
                    } else {
717
                        throw new IllegalStateException("Unknown requires modifier: " + name);
×
718
                    }
UNCOV
719
                }
×
UNCOV
720
                requires.put(MODULE_DESCRIPTOR_REQUIRES.name(require), new Requires.Simple(
×
UNCOV
721
                        (String) OPTIONAL.orElse(MODULE_DESCRIPTOR_REQUIRES.rawCompiledVersion(require), null),
×
722
                        modifiers));
UNCOV
723
            }
×
UNCOV
724
            return requires;
×
725
        }
726

727
        /**
728
         * {@inheritDoc}
729
         */
730
        public Map<String, Provides> getProvides() {
UNCOV
731
            Map<String, Provides> provides = new LinkedHashMap<String, Provides>();
×
UNCOV
732
            for (Object require : MODULE_DESCRIPTOR.provides(MODULE.getDescriptor(module))) {
×
UNCOV
733
                provides.put(MODULE_DESCRIPTOR_PROVIDES.service(require), new Provides.Simple(new LinkedHashSet<String>(MODULE_DESCRIPTOR_PROVIDES.providers(require))));
×
UNCOV
734
            }
×
UNCOV
735
            return provides;
×
736
        }
737

738
        /**
739
         * {@inheritDoc}
740
         */
741
        public int getModifiers() {
742
            int modifiers = 0;
×
743
            for (Enum<?> modifier : MODULE_DESCRIPTOR.modifiers(MODULE.getDescriptor(module))) {
×
744
                String name = modifier.name();
×
UNCOV
745
                if (name.equals("SYNTHETIC")) {
×
746
                    modifiers |= Opcodes.ACC_SYNTHETIC;
×
UNCOV
747
                } else if (name.equals("MANDATED")) {
×
748
                    modifiers |= Opcodes.ACC_MANDATED;
×
749
                } else if (name.equals("OPEN")) {
×
UNCOV
750
                    modifiers |= Opcodes.ACC_OPEN;
×
751
                } else {
UNCOV
752
                    throw new IllegalStateException("Unknown module modifier: " + name);
×
753
                }
UNCOV
754
            }
×
UNCOV
755
            return modifiers;
×
756
        }
757

758
        /**
759
         * {@inheritDoc}
760
         */
761
        public String getActualName() {
UNCOV
762
            return MODULE_DESCRIPTOR.name(MODULE.getDescriptor(module));
×
763
        }
764

765
        /**
766
         * {@inheritDoc}
767
         */
768
        public AnnotationList getDeclaredAnnotations() {
UNCOV
769
            return new AnnotationList.ForLoadedAnnotations(module.getDeclaredAnnotations());
×
770
        }
771

772
        /**
773
         * A proxy for interacting with {@code java.lang.Module}.
774
         */
775
        @JavaDispatcher.Proxied("java.lang.Module")
776
        protected interface Module {
777

778
            /**
779
             * Returns {@code true} if the supplied instance is of type {@code java.lang.Module}.
780
             *
781
             * @param value The instance to investigate.
782
             * @return {@code true} if the supplied value is a {@code java.lang.Module}.
783
             */
784
            @JavaDispatcher.Instance
785
            boolean isInstance(Object value);
786

787
            /**
788
             * Returns {@code true} if the supplied module is named.
789
             *
790
             * @param value The {@code java.lang.Module} to check for the existence of a name.
791
             * @return {@code true} if the supplied module is named.
792
             */
793
            boolean isNamed(Object value);
794

795
            /**
796
             * Returns the module's name.
797
             *
798
             * @param value The {@code java.lang.Module} to check for its name.
799
             * @return The module's (implicit or explicit) name.
800
             */
801
            String getName(Object value);
802

803
            /**
804
             * Returns the module's exported packages.
805
             *
806
             * @param value The {@code java.lang.Module} to check for its packages.
807
             * @return The module's packages.
808
             */
809
            Set<String> getPackages(Object value);
810

811
            /**
812
             * Returns the module descriptor.
813
             *
814
             * @param value The {@code java.lang.Module} to check for its descriptor.
815
             * @return The module's descriptor.
816
             */
817
            Object getDescriptor(Object value);
818
        }
819

820
        /**
821
         * A proxy for interacting with {@code java.lang.ModuleDescriptor}.
822
         */
823
        @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor")
824
        protected interface ModuleDescriptor {
825

826
            /**
827
             * Returns the module's name.
828
             *
829
             * @param value The {@code java.lang.ModuleDescriptor} instance.
830
             * @return The module's name.
831
             */
832
            String name(Object value);
833

834
            /**
835
             * Returns the module's modifiers.
836
             *
837
             * @param value The {@code java.lang.ModuleDescriptor} instance.
838
             * @return The module's modifiers.
839
             */
840
            Set<Enum<?>> modifiers(Object value);
841

842
            /**
843
             * Returns {@code true} if this is an open module.
844
             *
845
             * @param value The {@code java.lang.ModuleDescriptor} instance.
846
             * @return {@code true} if this is an open module.
847
             */
848
            boolean isOpen(Object value);
849

850
            /**
851
             * Returns the module's requires declarations.
852
             *
853
             * @param value The {@code java.lang.ModuleDescriptor} instance.
854
             * @return The module's requires declarations.
855
             */
856
            Set<?> requires(Object value);
857

858
            /**
859
             * Returns the module's exports declarations.
860
             *
861
             * @param value The {@code java.lang.ModuleDescriptor} instance.
862
             * @return The module's exports declarations.
863
             */
864
            Set<?> exports(Object value);
865

866
            /**
867
             * Returns the module's opens declarations.
868
             *
869
             * @param value The {@code java.lang.ModuleDescriptor} instance.
870
             * @return The module's opens declarations.
871
             */
872
            Set<?> opens(Object value);
873

874
            /**
875
             * Returns the module's uses declarations.
876
             *
877
             * @param value The {@code java.lang.ModuleDescriptor} instance.
878
             * @return The module's uses declarations.
879
             */
880
            Set<String> uses(Object value);
881

882
            /**
883
             * Returns the module's provides declarations.
884
             *
885
             * @param value The {@code java.lang.ModuleDescriptor} instance.
886
             * @return The module's provides declarations.
887
             */
888
            Set<?> provides(Object value);
889

890
            /**
891
             * Returns the module's raw version.
892
             *
893
             * @param value The {@code java.lang.ModuleDescriptor} instance.
894
             * @return The module's raw version as an {@code Optional}.
895
             */
896
            Object rawVersion(Object value);
897

898
            /**
899
             * Returns the module's main class.
900
             *
901
             * @param value The {@code java.lang.ModuleDescriptor} instance.
902
             * @return The module's main class as an {@code Optional}.
903
             */
904
            Object mainClass(Object value);
905

906
            /**
907
             * Returns the module's packages.
908
             *
909
             * @param value The {@code java.lang.ModuleDescriptor} instance.
910
             * @return The module's packages.
911
             */
912
            Set<String> packages(Object value);
913

914
            /**
915
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Requires}.
916
             */
917
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Requires")
918
            interface Requires {
919

920
                /**
921
                 * Returns the name of the required module.
922
                 *
923
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
924
                 * @return The name of the required module.
925
                 */
926
                String name(Object value);
927

928
                /**
929
                 * Returns the modifiers of the requires declaration.
930
                 *
931
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
932
                 * @return The modifiers of the requires declaration.
933
                 */
934
                Set<Enum<?>> modifiers(Object value);
935

936
                /**
937
                 * Returns the raw compiled version of the required module.
938
                 *
939
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
940
                 * @return The raw compiled version as an {@code Optional}.
941
                 */
942
                Object rawCompiledVersion(Object value);
943
            }
944

945
            /**
946
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Exports}.
947
             */
948
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Exports")
949
            interface Exports {
950

951
                /**
952
                 * Returns the source package name for this export.
953
                 *
954
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
955
                 * @return The source package name.
956
                 */
957
                String source(Object value);
958

959
                /**
960
                 * Returns the modifiers of the exports declaration.
961
                 *
962
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
963
                 * @return The modifiers of the exports declaration.
964
                 */
965
                Set<Enum<?>> modifiers(Object value);
966

967
                /**
968
                 * Returns the target modules for this export.
969
                 *
970
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
971
                 * @return The target modules for this export.
972
                 */
973
                Set<String> targets(Object value);
974
            }
975

976
            /**
977
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Opens}.
978
             */
979
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Opens")
980
            interface Opens {
981

982
                /**
983
                 * Returns the source package name for this opens declaration.
984
                 *
985
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
986
                 * @return The source package name.
987
                 */
988
                String source(Object value);
989

990
                /**
991
                 * Returns the modifiers of the opens declaration.
992
                 *
993
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
994
                 * @return The modifiers of the opens declaration.
995
                 */
996
                Set<Enum<?>> modifiers(Object value);
997

998
                /**
999
                 * Returns the target modules for this opens declaration.
1000
                 *
1001
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
1002
                 * @return The target modules for this opens declaration.
1003
                 */
1004
                Set<String> targets(Object value);
1005
            }
1006

1007
            /**
1008
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Provides}.
1009
             */
1010
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Provides")
1011
            interface Provides {
1012

1013
                /**
1014
                 * Returns the service interface name for this provides declaration.
1015
                 *
1016
                 * @param value The {@code java.lang.ModuleDescriptor.Provides} instance.
1017
                 * @return The service interface name.
1018
                 */
1019
                String service(Object value);
1020

1021
                /**
1022
                 * Returns the provider implementation class names for this provides declaration.
1023
                 *
1024
                 * @param value The {@code java.lang.ModuleDescriptor.Provides} instance.
1025
                 * @return The provider implementation class names.
1026
                 */
1027
                List<String> providers(Object value);
1028
            }
1029
        }
1030

1031
        /**
1032
         * A proxy for interacting with {@code java.util.Optional}.
1033
         */
1034
        @JavaDispatcher.Proxied("java.util.Optional")
1035
        protected interface Optional {
1036

1037
            /**
1038
             * Returns the value if present, otherwise returns the fallback value.
1039
             *
1040
             * @param value    The {@code java.util.Optional} instance.
1041
             * @param fallback The fallback value to return if the optional is empty.
1042
             * @return The value if present, otherwise the fallback value.
1043
             */
1044
            @MaybeNull
1045
            Object orElse(Object value, @MaybeNull Object fallback);
1046
        }
1047
    }
1048

1049
    /**
1050
     * A latent description of a module.
1051
     */
1052
    class Latent extends AbstractBase {
1053

1054
        /**
1055
         * The name of the module.
1056
         */
1057
        private final String name;
1058

1059
        /**
1060
         * The modifiers of the module.
1061
         */
1062
        private final int modifiers;
1063

1064
        /**
1065
         * The module version or {@code null} if no version was specified.
1066
         */
1067
        @MaybeNull
1068
        private final String version;
1069

1070
        /**
1071
         * The module's main class or {@code null} if no main class was specified.
1072
         */
1073
        @MaybeNull
1074
        private final String mainClass;
1075

1076
        /**
1077
         * The module's packages.
1078
         */
1079
        private final Set<String> packages;
1080

1081
        /**
1082
         * The modules that this module requires.
1083
         */
1084
        private final Map<String, ModuleDescription.Requires> requires;
1085

1086
        /**
1087
         * The packages that this module exports.
1088
         */
1089
        private final Map<String, ModuleDescription.Exports> exports;
1090

1091
        /**
1092
         * The package that this module opens.
1093
         */
1094
        private final Map<String, ModuleDescription.Opens> opens;
1095

1096
        /**
1097
         * The services that this module uses.
1098
         */
1099
        private final Set<String> uses;
1100

1101
        /**
1102
         * The services that this module provides.
1103
         */
1104
        private final Map<String, ModuleDescription.Provides> provides;
1105

1106
        /**
1107
         * A list of annotations on the described module.
1108
         */
1109
        private final List<? extends AnnotationDescription> annotations;
1110

1111
        /**
1112
         * Creates a new latent module description.
1113
         *
1114
         * @param name        The name of the module.
1115
         * @param modifiers   The modifiers of the module.
1116
         * @param version     The module version or {@code null} if no version was specified.
1117
         * @param mainClass   The module's main class or {@code null} if no main class was specified.
1118
         * @param packages    The module's packages.
1119
         * @param requires    The modules that this module requires.
1120
         * @param exports     The packages that this module exports.
1121
         * @param opens       The package that this module opens.
1122
         * @param uses        The services that this module uses.
1123
         * @param provides    The services that this module provides.
1124
         * @param annotations A list of annotations on the described module.
1125
         */
1126
        public Latent(String name,
1127
                      int modifiers,
1128
                      @MaybeNull String version,
1129
                      @MaybeNull String mainClass,
1130
                      Set<String> packages,
1131
                      Map<String, Requires> requires,
1132
                      Map<String, Exports> exports,
1133
                      Map<String, Opens> opens,
1134
                      Set<String> uses,
1135
                      Map<String, Provides> provides,
UNCOV
1136
                      List<? extends AnnotationDescription> annotations) {
×
UNCOV
1137
            this.name = name;
×
UNCOV
1138
            this.modifiers = modifiers;
×
UNCOV
1139
            this.version = version;
×
UNCOV
1140
            this.mainClass = mainClass;
×
UNCOV
1141
            this.packages = packages;
×
UNCOV
1142
            this.requires = requires;
×
UNCOV
1143
            this.exports = exports;
×
UNCOV
1144
            this.opens = opens;
×
UNCOV
1145
            this.uses = uses;
×
UNCOV
1146
            this.provides = provides;
×
UNCOV
1147
            this.annotations = annotations;
×
UNCOV
1148
        }
×
1149

1150
        /**
1151
         * {@inheritDoc}
1152
         */
1153
        @MaybeNull
1154
        public String getVersion() {
UNCOV
1155
            return version;
×
1156
        }
1157

1158
        /**
1159
         * {@inheritDoc}
1160
         */
1161
        @MaybeNull
1162
        public String getMainClass() {
UNCOV
1163
            return mainClass;
×
1164
        }
1165

1166
        /**
1167
         * {@inheritDoc}
1168
         */
1169
        public Set<String> getPackages() {
UNCOV
1170
            return packages;
×
1171
        }
1172

1173
        /**
1174
         * {@inheritDoc}
1175
         */
1176
        public Map<String, Exports> getExports() {
UNCOV
1177
            return exports;
×
1178
        }
1179

1180
        /**
1181
         * {@inheritDoc}
1182
         */
1183
        public Map<String, Opens> getOpens() {
UNCOV
1184
            return opens;
×
1185
        }
1186

1187
        /**
1188
         * {@inheritDoc}
1189
         */
1190
        public Map<String, Requires> getRequires() {
UNCOV
1191
            return requires;
×
1192
        }
1193

1194
        /**
1195
         * {@inheritDoc}
1196
         */
1197
        public Set<String> getUses() {
UNCOV
1198
            return uses;
×
1199
        }
1200

1201
        /**
1202
         * {@inheritDoc}
1203
         */
1204
        public Map<String, Provides> getProvides() {
UNCOV
1205
            return provides;
×
1206
        }
1207

1208
        /**
1209
         * {@inheritDoc}
1210
         */
1211
        public int getModifiers() {
UNCOV
1212
            return modifiers;
×
1213
        }
1214

1215
        /**
1216
         * {@inheritDoc}
1217
         */
1218
        public String getActualName() {
UNCOV
1219
            return name;
×
1220
        }
1221

1222
        /**
1223
         * {@inheritDoc}
1224
         */
1225
        public AnnotationList getDeclaredAnnotations() {
UNCOV
1226
            return new AnnotationList.Explicit(annotations);
×
1227
        }
1228
    }
1229
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc