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

raphw / byte-buddy / #808

29 Oct 2025 11:21AM UTC coverage: 84.614% (-0.3%) from 84.915%
#808

push

raphw
Add support for writing out module information from type writer.

8 of 135 new or added lines in 2 files covered. (5.93%)

29785 of 35201 relevant lines covered (84.61%)

0.85 hits per line

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

28.88
/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.AnnotationList;
22
import net.bytebuddy.description.annotation.AnnotationSource;
23
import net.bytebuddy.utility.dispatcher.JavaDispatcher;
24
import net.bytebuddy.utility.nullability.AlwaysNull;
25
import net.bytebuddy.utility.nullability.MaybeNull;
26
import org.objectweb.asm.ClassVisitor;
27
import org.objectweb.asm.ModuleVisitor;
28
import org.objectweb.asm.Opcodes;
29

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

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

46
    /**
47
     * Defines a module that is not resolved.
48
     */
49
    @AlwaysNull
50
    ModuleDescription UNDEFINED = null;
1✔
51

52
    /**
53
     * Writes this module description as meta data to the provided {@link ClassVisitor}.
54
     *
55
     * @param classVisitor The class visitor to write to.
56
     */
57
    void accept(ClassVisitor classVisitor);
58

59
    /**
60
     * Returns the version of this module.
61
     *
62
     * @return The module's version or {@code null} if no version is specified.
63
     */
64
    @MaybeNull
65
    String getVersion();
66

67
    /**
68
     * Returns the main class of this module.
69
     *
70
     * @return The module's main class or {@code null} if no main class is specified.
71
     */
72
    @MaybeNull
73
    String getMainClass();
74

75
    /**
76
     * Returns all packages contained in this module.
77
     *
78
     * @return A set of all package names within this module.
79
     */
80
    Set<String> getPackages();
81

82
    /**
83
     * Returns all package exports of this module.
84
     *
85
     * @return A mapping of package names to their export declarations.
86
     */
87
    Map<String, Exports> getExports();
88

89
    /**
90
     * Returns all package opens of this module.
91
     *
92
     * @return A mapping of package names to their opens declarations.
93
     */
94
    Map<String, Opens> getOpens();
95

96
    /**
97
     * Returns all module dependencies of this module.
98
     *
99
     * @return A mapping of module names to their require declarations.
100
     */
101
    Map<String, Requires> getRequires();
102

103
    /**
104
     * Returns all service types that this module uses.
105
     *
106
     * @return A set of service class names that this module uses.
107
     */
108
    Set<String> getUses();
109

110
    /**
111
     * Returns all service implementations provided by this module.
112
     *
113
     * @return A mapping of service names to their provider declarations.
114
     */
115
    Map<String, Provides> getProvides();
116

117
    /**
118
     * Represents an exported package declaration in a module. Exports control which packages
119
     * are accessible to other modules.
120
     */
121
    interface Exports extends ModifierReviewable.OfMandatable {
122

123
        /**
124
         * Returns the target modules that this package is exported to.
125
         *
126
         * @return A set of module names that can access this exported package, or an empty set if exported to all modules.
127
         */
128
        Set<String> getTargets();
129

130
        /**
131
         * Determines if this export is qualified (exported to specific modules only).
132
         *
133
         * @return {@code true} if this export has specific target modules, {@code false} if exported to all modules.
134
         */
135
        boolean isQualified();
136

137
        /**
138
         * An abstract base implementation of {@link Exports} that provides a default implementation
139
         * for {@link #isQualified()}.
140
         */
141
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Exports {
1✔
142

143
            /**
144
             * {@inheritDoc}
145
             */
146
            public boolean isQualified() {
147
                return !getTargets().isEmpty();
×
148
            }
149

150
            @Override
151
            public int hashCode() {
152
                int hashCode = getModifiers();
1✔
153
                return hashCode + 17 * getTargets().hashCode();
1✔
154
            }
155

156
            @Override
157
            public boolean equals(Object other) {
158
                if (!(other instanceof Exports)) return false;
1✔
159
                Exports exports = (Exports) other;
1✔
160
                return getModifiers() == exports.getModifiers() && getTargets().equals(exports.getTargets());
1✔
161
            }
162

163
            @Override
164
            public String toString() {
165
                return "Opens{"
×
166
                        + "targets=" + getTargets()
×
167
                        + ",modifiers=" + getModifiers()
×
168
                        + '}';
169
            }
170
        }
171

172
        /**
173
         * A simple implementation of {@link Exports} that stores the target modules and modifiers.
174
         */
175
        class Simple extends AbstractBase {
176

177
            /**
178
             * The target modules for this export.
179
             */
180
            private final Set<String> targets;
181

182
            /**
183
             * The modifiers for this export.
184
             */
185
            protected final int modifiers;
186

187
            /**
188
             * Creates a new simple export declaration.
189
             *
190
             * @param targets   The target modules for this export.
191
             * @param modifiers The modifiers for this export.
192
             */
193
            public Simple(Set<String> targets, int modifiers) {
1✔
194
                this.targets = targets;
1✔
195
                this.modifiers = modifiers;
1✔
196
            }
1✔
197

198
            /**
199
             * {@inheritDoc}
200
             */
201
            public Set<String> getTargets() {
202
                return targets;
1✔
203
            }
204

205
            /**
206
             * {@inheritDoc}
207
             */
208
            public int getModifiers() {
209
                return modifiers;
1✔
210
            }
211
        }
212
    }
213

214
    /**
215
     * Represents an opened package declaration in a module. Opens allow deep reflective access
216
     * to packages for other modules.
217
     */
218
    interface Opens extends ModifierReviewable.OfMandatable {
219

220
        /**
221
         * Returns the target modules that this package is opened to.
222
         *
223
         * @return A set of module names that can reflectively access this opened package, or an empty set if opened to all modules.
224
         */
225
        Set<String> getTargets();
226

227
        /**
228
         * Determines if this opens declaration is qualified (opened to specific modules only).
229
         *
230
         * @return {@code true} if this opens has specific target modules, {@code false} if opened to all modules.
231
         */
232
        boolean isQualified();
233

234
        /**
235
         * An abstract base implementation of {@link Opens}.
236
         */
237
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Opens {
1✔
238

239
            /**
240
             * {@inheritDoc}
241
             */
242
            public boolean isQualified() {
243
                return !getTargets().isEmpty();
×
244
            }
245

246
            @Override
247
            public int hashCode() {
248
                int hashCode = getModifiers();
1✔
249
                return hashCode + 17 * getTargets().hashCode();
1✔
250
            }
251

252
            @Override
253
            public boolean equals(Object other) {
254
                if (!(other instanceof Opens)) return false;
1✔
255
                Opens opens = (Opens) other;
1✔
256
                return getModifiers() == opens.getModifiers() && getTargets().equals(opens.getTargets());
1✔
257
            }
258

259
            @Override
260
            public String toString() {
261
                return "Opens{"
×
262
                        + "targets=" + getTargets()
×
263
                        + ",modifiers=" + getModifiers()
×
264
                        + '}';
265
            }
266
        }
267

268
        /**
269
         * A simple implementation of {@link Opens}.
270
         */
271
        class Simple extends AbstractBase {
272

273
            /**
274
             * The target modules for this opens declaration.
275
             */
276
            private final Set<String> targets;
277

278
            /**
279
             * The modifiers for this opens declaration.
280
             */
281
            protected final int modifiers;
282

283
            /**
284
             * Creates a new simple opens declaration.
285
             *
286
             * @param targets   The target modules for this opens declaration.
287
             * @param modifiers The modifiers for this opens declaration.
288
             */
289
            public Simple(Set<String> targets, int modifiers) {
1✔
290
                this.targets = targets;
1✔
291
                this.modifiers = modifiers;
1✔
292
            }
1✔
293

294
            /**
295
             * {@inheritDoc}
296
             */
297
            public Set<String> getTargets() {
298
                return targets;
1✔
299
            }
300

301
            /**
302
             * {@inheritDoc}
303
             */
304
            public int getModifiers() {
305
                return modifiers;
1✔
306
            }
307
        }
308
    }
309

310
    /**
311
     * Represents a module dependency declaration. Requires specify which modules this module
312
     * depends on for compilation and runtime.
313
     */
314
    interface Requires extends ModifierReviewable.ForModuleRequirement {
315

316
        /**
317
         * Returns the version of the required module.
318
         *
319
         * @return The required module's version or {@code null} if no specific version is required.
320
         */
321
        @MaybeNull
322
        String getVersion();
323

324
        /**
325
         * An abstract base implementation of {@link Requires}.
326
         */
327
        abstract class AbstractBase extends ModifierReviewable.AbstractBase implements Requires {
1✔
328

329
            @Override
330
            public int hashCode() {
331
                int hashCode = getModifiers();
1✔
332
                String version = getVersion();
1✔
333
                return version == null ? hashCode : (hashCode + 17 * version.hashCode());
1✔
334
            }
335

336
            @Override
337
            public boolean equals(Object other) {
338
                if (!(other instanceof Requires)) return false;
1✔
339
                Requires requires = (Requires) other;
1✔
340
                String version = getVersion();
1✔
341
                return getModifiers() == requires.getModifiers() && version == null ? requires.getVersion() == null : version.equals(requires.getVersion());
1✔
342
            }
343

344
            @Override
345
            public String toString() {
346
                String version = getVersion();
×
347
                return "Requires{"
×
348
                        + "version=" + (version == null ? "" : '"' + version + '\'')
349
                        + ",modifiers=" + getModifiers()
×
350
                        + '}';
351
            }
352
        }
353

354
        /**
355
         * A simple implementation of {@link Requires}.
356
         */
357
        class Simple extends AbstractBase {
358

359
            /**
360
             * The version of the required module.
361
             */
362
            @MaybeNull
363
            private final String version;
364

365
            /**
366
             * The modifiers for this requires declaration.
367
             */
368
            private final int modifiers;
369

370
            /**
371
             * Creates a new simple requires declaration.
372
             *
373
             * @param version   The version of the required module or {@code null} if no specific version is required.
374
             * @param modifiers The modifiers for this requires declaration.
375
             */
376
            public Simple(@MaybeNull String version, int modifiers) {
1✔
377
                this.version = version;
1✔
378
                this.modifiers = modifiers;
1✔
379
            }
1✔
380

381
            /**
382
             * {@inheritDoc}
383
             */
384
            @MaybeNull
385
            public String getVersion() {
386
                return version;
1✔
387
            }
388

389
            /**
390
             * {@inheritDoc}
391
             */
392
            public int getModifiers() {
393
                return modifiers;
1✔
394
            }
395
        }
396
    }
397

398
    /**
399
     * Represents a service provider declaration in a module. Provides specify which service
400
     * implementations this module offers to other modules.
401
     */
402
    interface Provides {
403

404
        /**
405
         * Returns the implementation classes that provide the service.
406
         *
407
         * @return A set of class names that implement the service.
408
         */
409
        Set<String> getProviders();
410

411
        /**
412
         * An abstract base implementation of {@link Provides}.
413
         */
414
        abstract class AbstractBase implements Provides {
1✔
415

416
            @Override
417
            public int hashCode() {
418
                return getProviders().hashCode();
1✔
419
            }
420

421
            @Override
422
            public boolean equals(Object other) {
423
                if (!(other instanceof Provides)) return false;
1✔
424
                Provides provides = (Provides) other;
1✔
425
                return getProviders().equals(provides.getProviders());
1✔
426
            }
427

428
            @Override
429
            public String toString() {
430
                return "Provides{providers=" + getProviders() + '}';
×
431
            }
432
        }
433

434
        /**
435
         * A simple implementation of {@link Provides}.
436
         */
437
        class Simple extends AbstractBase {
438

439
            /**
440
             * The implementation classes that provide the service.
441
             */
442
            private final Set<String> providers;
443

444
            /**
445
             * Creates a new simple provides declaration.
446
             *
447
             * @param providers The implementation classes that provide the service.
448
             */
449
            public Simple(Set<String> providers) {
1✔
450
                this.providers = providers;
1✔
451
            }
1✔
452

453
            /**
454
             * {@inheritDoc}
455
             */
456
            public Set<String> getProviders() {
457
                return providers;
1✔
458
            }
459
        }
460
    }
461

462
    /**
463
     * An abstract base implementation of a {@link ModuleDescription}.
464
     */
465
    abstract class AbstractBase extends ModifierReviewable.AbstractBase implements ModuleDescription {
1✔
466

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

510
        @Override
511
        public int hashCode() {
512
            return 17 * getActualName().hashCode();
1✔
513
        }
514

515
        @Override
516
        public boolean equals(Object other) {
517
            if (!(other instanceof ModuleDescription)) return false;
1✔
518
            ModuleDescription module = (ModuleDescription) other;
1✔
519
            return getActualName().equals(module.getActualName());
1✔
520
        }
521

522
        @Override
523
        public String toString() {
524
            return "module " + getActualName();
1✔
525
        }
526
    }
527

528
    /**
529
     * A {@link ModuleDescription} implementation that represents a loaded Java module.
530
     * This implementation uses reflection and Java dispatchers to access module information
531
     * from the runtime module system.
532
     */
533
    class ForLoadedModule extends AbstractBase {
534

535
        /**
536
         * A dispatcher for accessing {@code java.lang.Module} methods.
537
         */
538
        protected static final Module MODULE = doPrivileged(JavaDispatcher.of(Module.class));
×
539

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

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

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

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

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

565
        /**
566
         * A dispatcher for accessing {@code java.util.Optional} methods.
567
         */
568
        protected static final Optional OPTIONAL = doPrivileged(JavaDispatcher.of(Optional.class));
×
569

570
        /**
571
         * The module represented by this description.
572
         */
573
        private final AnnotatedElement module;
574

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

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

603
        /**
604
         * Creates a new module description for the supplied module.
605
         *
606
         * @param module The module to represent.
607
         */
608
        protected ForLoadedModule(AnnotatedElement module) {
×
609
            this.module = module;
×
610
        }
×
611

612
        /**
613
         * {@inheritDoc}
614
         */
615
        @MaybeNull
616
        public String getVersion() {
617
            return (String) OPTIONAL.orElse(MODULE_DESCRIPTOR.rawVersion(MODULE.getDescriptor(module)), null);
×
618
        }
619

620
        /**
621
         * {@inheritDoc}
622
         */
623
        @MaybeNull
624
        public String getMainClass() {
625
            return (String) OPTIONAL.orElse(MODULE_DESCRIPTOR.mainClass(MODULE.getDescriptor(module)), null);
×
626
        }
627

628
        /**
629
         * {@inheritDoc}
630
         */
631
        public boolean isOpen() {
632
            return MODULE_DESCRIPTOR.isOpen(MODULE.getDescriptor(module));
×
633
        }
634

635
        /**
636
         * {@inheritDoc}
637
         */
638
        public Set<String> getPackages() {
639
            return MODULE_DESCRIPTOR.packages(MODULE.getDescriptor(module));
×
640
        }
641

642
        /**
643
         * {@inheritDoc}
644
         */
645
        public Set<String> getUses() {
646
            return MODULE_DESCRIPTOR.uses(MODULE.getDescriptor(module));
×
647
        }
648

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

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

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

721
        /**
722
         * {@inheritDoc}
723
         */
724
        public Map<String, Provides> getProvides() {
725
            Map<String, Provides> provides = new LinkedHashMap<String, Provides>();
×
726
            for (Object require : MODULE_DESCRIPTOR.provides(MODULE.getDescriptor(module))) {
×
727
                provides.put(MODULE_DESCRIPTOR_PROVIDES.service(require), new Provides.Simple(new LinkedHashSet<String>(MODULE_DESCRIPTOR_PROVIDES.providers(require))));
×
728
            }
×
729
            return provides;
×
730
        }
731

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

752
        /**
753
         * {@inheritDoc}
754
         */
755
        public String getActualName() {
756
            return MODULE_DESCRIPTOR.name(MODULE.getDescriptor(module));
×
757
        }
758

759
        /**
760
         * {@inheritDoc}
761
         */
762
        public AnnotationList getDeclaredAnnotations() {
763
            return new AnnotationList.ForLoadedAnnotations(module.getDeclaredAnnotations());
×
764
        }
765

766
        /**
767
         * A proxy for interacting with {@code java.lang.Module}.
768
         */
769
        @JavaDispatcher.Proxied("java.lang.Module")
770
        protected interface Module {
771

772
            /**
773
             * Returns {@code true} if the supplied instance is of type {@code java.lang.Module}.
774
             *
775
             * @param value The instance to investigate.
776
             * @return {@code true} if the supplied value is a {@code java.lang.Module}.
777
             */
778
            @JavaDispatcher.Instance
779
            boolean isInstance(Object value);
780

781
            /**
782
             * Returns {@code true} if the supplied module is named.
783
             *
784
             * @param value The {@code java.lang.Module} to check for the existence of a name.
785
             * @return {@code true} if the supplied module is named.
786
             */
787
            boolean isNamed(Object value);
788

789
            /**
790
             * Returns the module's name.
791
             *
792
             * @param value The {@code java.lang.Module} to check for its name.
793
             * @return The module's (implicit or explicit) name.
794
             */
795
            String getName(Object value);
796

797
            /**
798
             * Returns the module's exported packages.
799
             *
800
             * @param value The {@code java.lang.Module} to check for its packages.
801
             * @return The module's packages.
802
             */
803
            Set<String> getPackages(Object value);
804

805
            /**
806
             * Returns the module descriptor.
807
             * @param value The {@code java.lang.Module} to check for its descriptor.
808
             * @return The module's descriptor.
809
             */
810
            Object getDescriptor(Object value);
811
        }
812

813
        /**
814
         * A proxy for interacting with {@code java.lang.ModuleDescriptor}.
815
         */
816
        @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor")
817
        protected interface ModuleDescriptor {
818

819
            /**
820
             * Returns the module's name.
821
             *
822
             * @param value The {@code java.lang.ModuleDescriptor} instance.
823
             * @return The module's name.
824
             */
825
            String name(Object value);
826

827
            /**
828
             * Returns the module's modifiers.
829
             *
830
             * @param value The {@code java.lang.ModuleDescriptor} instance.
831
             * @return The module's modifiers.
832
             */
833
            Set<Enum<?>> modifiers(Object value);
834

835
            /**
836
             * Returns {@code true} if this is an open module.
837
             *
838
             * @param value The {@code java.lang.ModuleDescriptor} instance.
839
             * @return {@code true} if this is an open module.
840
             */
841
            boolean isOpen(Object value);
842

843
            /**
844
             * Returns the module's requires declarations.
845
             *
846
             * @param value The {@code java.lang.ModuleDescriptor} instance.
847
             * @return The module's requires declarations.
848
             */
849
            Set<?> requires(Object value);
850

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

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

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

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

883
            /**
884
             * Returns the module's raw version.
885
             *
886
             * @param value The {@code java.lang.ModuleDescriptor} instance.
887
             * @return The module's raw version as an {@code Optional}.
888
             */
889
            Object rawVersion(Object value);
890

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

899
            /**
900
             * Returns the module's packages.
901
             *
902
             * @param value The {@code java.lang.ModuleDescriptor} instance.
903
             * @return The module's packages.
904
             */
905
            Set<String> packages(Object value);
906

907
            /**
908
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Requires}.
909
             */
910
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Requires")
911
            interface Requires {
912

913
                /**
914
                 * Returns the name of the required module.
915
                 *
916
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
917
                 * @return The name of the required module.
918
                 */
919
                String name(Object value);
920

921
                /**
922
                 * Returns the modifiers of the requires declaration.
923
                 *
924
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
925
                 * @return The modifiers of the requires declaration.
926
                 */
927
                Set<Enum<?>> modifiers(Object value);
928

929
                /**
930
                 * Returns the raw compiled version of the required module.
931
                 *
932
                 * @param value The {@code java.lang.ModuleDescriptor.Requires} instance.
933
                 * @return The raw compiled version as an {@code Optional}.
934
                 */
935
                Object rawCompiledVersion(Object value);
936
            }
937

938
            /**
939
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Exports}.
940
             */
941
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Exports")
942
            interface Exports {
943

944
                /**
945
                 * Returns the source package name for this export.
946
                 *
947
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
948
                 * @return The source package name.
949
                 */
950
                String source(Object value);
951

952
                /**
953
                 * Returns the modifiers of the exports declaration.
954
                 *
955
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
956
                 * @return The modifiers of the exports declaration.
957
                 */
958
                Set<Enum<?>> modifiers(Object value);
959

960
                /**
961
                 * Returns the target modules for this export.
962
                 *
963
                 * @param value The {@code java.lang.ModuleDescriptor.Exports} instance.
964
                 * @return The target modules for this export.
965
                 */
966
                Set<String> targets(Object value);
967
            }
968

969
            /**
970
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Opens}.
971
             */
972
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Opens")
973
            interface Opens {
974

975
                /**
976
                 * Returns the source package name for this opens declaration.
977
                 *
978
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
979
                 * @return The source package name.
980
                 */
981
                String source(Object value);
982

983
                /**
984
                 * Returns the modifiers of the opens declaration.
985
                 *
986
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
987
                 * @return The modifiers of the opens declaration.
988
                 */
989
                Set<Enum<?>> modifiers(Object value);
990

991
                /**
992
                 * Returns the target modules for this opens declaration.
993
                 *
994
                 * @param value The {@code java.lang.ModuleDescriptor.Opens} instance.
995
                 * @return The target modules for this opens declaration.
996
                 */
997
                Set<String> targets(Object value);
998
            }
999

1000
            /**
1001
             * A proxy for interacting with {@code java.lang.ModuleDescriptor.Provides}.
1002
             */
1003
            @JavaDispatcher.Proxied("java.lang.module.ModuleDescriptor$Provides")
1004
            interface Provides {
1005

1006
                /**
1007
                 * Returns the service interface name for this provides declaration.
1008
                 *
1009
                 * @param value The {@code java.lang.ModuleDescriptor.Provides} instance.
1010
                 * @return The service interface name.
1011
                 */
1012
                String service(Object value);
1013

1014
                /**
1015
                 * Returns the provider implementation class names for this provides declaration.
1016
                 *
1017
                 * @param value The {@code java.lang.ModuleDescriptor.Provides} instance.
1018
                 * @return The provider implementation class names.
1019
                 */
1020
                List<String> providers(Object value);
1021
            }
1022
        }
1023

1024
        /**
1025
         * A proxy for interacting with {@code java.util.Optional}.
1026
         */
1027
        @JavaDispatcher.Proxied("java.util.Optional")
1028
        protected interface Optional {
1029

1030
            /**
1031
             * Returns the value if present, otherwise returns the fallback value.
1032
             *
1033
             * @param value    The {@code java.util.Optional} instance.
1034
             * @param fallback The fallback value to return if the optional is empty.
1035
             * @return The value if present, otherwise the fallback value.
1036
             */
1037
            @MaybeNull
1038
            Object orElse(Object value, @MaybeNull Object fallback);
1039
        }
1040
    }
1041
}
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