1 /*
  2  * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.classfile.impl;
 26 
 27 import java.lang.classfile.*;
 28 import java.lang.classfile.attribute.*;
 29 import java.lang.classfile.constantpool.ClassEntry;
 30 import java.lang.classfile.constantpool.ConstantValueEntry;
 31 import java.lang.classfile.constantpool.ModuleEntry;
 32 import java.lang.classfile.constantpool.NameAndTypeEntry;
 33 import java.lang.classfile.constantpool.PackageEntry;
 34 import java.lang.classfile.constantpool.Utf8Entry;
 35 import java.util.Collection;
 36 import java.util.List;
 37 import java.util.Optional;
 38 
 39 import jdk.internal.access.SharedSecrets;
 40 
 41 import static java.util.Objects.requireNonNull;
 42 
 43 public abstract sealed class UnboundAttribute<T extends Attribute<T>>
 44         extends AbstractElement
 45         implements Attribute<T>, Util.Writable {
 46     protected final AttributeMapper<T> mapper;
 47 
 48     public UnboundAttribute(AttributeMapper<T> mapper) {
 49         this.mapper = mapper;
 50     }
 51 
 52     @Override
 53     public AttributeMapper<T> attributeMapper() {
 54         return mapper;
 55     }
 56 
 57     @Override
 58     public String attributeName() {
 59         return mapper.name();
 60     }
 61 
 62     @Override
 63     @SuppressWarnings("unchecked")
 64     public void writeTo(BufWriterImpl buf) {
 65         mapper.writeAttribute(buf, (T) this);
 66     }
 67 
 68     @Override
 69     public void writeTo(DirectClassBuilder builder) {
 70         builder.writeAttribute(this);
 71     }
 72 
 73     @Override
 74     public void writeTo(DirectCodeBuilder builder) {
 75         builder.writeAttribute(this);
 76     }
 77 
 78     @Override
 79     public void writeTo(DirectMethodBuilder builder) {
 80         builder.writeAttribute(this);
 81     }
 82 
 83     @Override
 84     public void writeTo(DirectFieldBuilder builder) {
 85         builder.writeAttribute(this);
 86     }
 87 
 88     @Override
 89     public String toString() {
 90         return String.format("Attribute[name=%s]", mapper.name());
 91     }
 92     public static final class UnboundConstantValueAttribute
 93             extends UnboundAttribute<ConstantValueAttribute>
 94             implements ConstantValueAttribute {
 95 
 96         private final ConstantValueEntry entry;
 97 
 98         public UnboundConstantValueAttribute(ConstantValueEntry entry) {
 99             super(Attributes.constantValue());
100             this.entry = requireNonNull(entry);
101         }
102 
103         @Override
104         public ConstantValueEntry constant() {
105             return entry;
106         }
107 
108     }
109 
110     public static final class UnboundDeprecatedAttribute
111             extends UnboundAttribute<DeprecatedAttribute>
112             implements DeprecatedAttribute {
113         public UnboundDeprecatedAttribute() {
114             super(Attributes.deprecated());
115         }
116     }
117 
118     public static final class UnboundSyntheticAttribute
119             extends UnboundAttribute<SyntheticAttribute>
120             implements SyntheticAttribute {
121         public UnboundSyntheticAttribute() {
122             super(Attributes.synthetic());
123         }
124     }
125 
126     public static final class UnboundSignatureAttribute
127             extends UnboundAttribute<SignatureAttribute>
128             implements SignatureAttribute {
129         private final Utf8Entry signature;
130 
131         public UnboundSignatureAttribute(Utf8Entry signature) {
132             super(Attributes.signature());
133             this.signature = requireNonNull(signature);
134         }
135 
136         @Override
137         public Utf8Entry signature() {
138             return signature;
139         }
140     }
141 
142     public static final class UnboundExceptionsAttribute
143             extends UnboundAttribute<ExceptionsAttribute>
144             implements ExceptionsAttribute {
145         private final List<ClassEntry> exceptions;
146 
147         public UnboundExceptionsAttribute(List<ClassEntry> exceptions) {
148             super(Attributes.exceptions());
149             this.exceptions = List.copyOf(exceptions);
150         }
151 
152         @Override
153         public List<ClassEntry> exceptions() {
154             return exceptions;
155         }
156     }
157 
158     public static final class UnboundAnnotationDefaultAttribute
159             extends UnboundAttribute<AnnotationDefaultAttribute>
160             implements AnnotationDefaultAttribute {
161         private final AnnotationValue annotationDefault;
162 
163         public UnboundAnnotationDefaultAttribute(AnnotationValue annotationDefault) {
164             super(Attributes.annotationDefault());
165             this.annotationDefault = requireNonNull(annotationDefault);
166         }
167 
168         @Override
169         public AnnotationValue defaultValue() {
170             return annotationDefault;
171         }
172     }
173 
174     public static final class UnboundSourceFileAttribute extends UnboundAttribute<SourceFileAttribute>
175             implements SourceFileAttribute {
176         private final Utf8Entry sourceFile;
177 
178         public UnboundSourceFileAttribute(Utf8Entry sourceFile) {
179             super(Attributes.sourceFile());
180             this.sourceFile = requireNonNull(sourceFile);
181         }
182 
183         @Override
184         public Utf8Entry sourceFile() {
185             return sourceFile;
186         }
187 
188     }
189 
190     public static final class UnboundStackMapTableAttribute extends UnboundAttribute<StackMapTableAttribute>
191             implements StackMapTableAttribute {
192         private final List<StackMapFrameInfo> entries;
193 
194         public UnboundStackMapTableAttribute(List<StackMapFrameInfo> entries) {
195             super(Attributes.stackMapTable());
196             this.entries = List.copyOf(entries);
197         }
198 
199         @Override
200         public List<StackMapFrameInfo> entries() {
201             return entries;
202         }
203     }
204 
205     public static final class UnboundInnerClassesAttribute
206             extends UnboundAttribute<InnerClassesAttribute>
207             implements InnerClassesAttribute {
208         private final List<InnerClassInfo> innerClasses;
209 
210         public UnboundInnerClassesAttribute(List<InnerClassInfo> innerClasses) {
211             super(Attributes.innerClasses());
212             this.innerClasses = List.copyOf(innerClasses);
213         }
214 
215         @Override
216         public List<InnerClassInfo> classes() {
217             return innerClasses;
218         }
219     }
220 
221     public static final class UnboundRecordAttribute
222             extends UnboundAttribute<RecordAttribute>
223             implements RecordAttribute {
224         private final List<RecordComponentInfo> components;
225 
226         public UnboundRecordAttribute(List<RecordComponentInfo> components) {
227             super(Attributes.record());
228             this.components = List.copyOf(components);
229         }
230 
231         @Override
232         public List<RecordComponentInfo> components() {
233             return components;
234         }
235     }
236 
237     public static final class UnboundEnclosingMethodAttribute
238             extends UnboundAttribute<EnclosingMethodAttribute>
239             implements EnclosingMethodAttribute {
240         private final ClassEntry classEntry;
241         private final NameAndTypeEntry method;
242 
243         public UnboundEnclosingMethodAttribute(ClassEntry classEntry, NameAndTypeEntry method) {
244             super(Attributes.enclosingMethod());
245             this.classEntry = requireNonNull(classEntry);
246             this.method = method;
247         }
248 
249         @Override
250         public ClassEntry enclosingClass() {
251             return classEntry;
252         }
253 
254         @Override
255         public Optional<NameAndTypeEntry> enclosingMethod() {
256             return Optional.ofNullable(method);
257         }
258     }
259 
260     public static final class UnboundMethodParametersAttribute
261             extends UnboundAttribute<MethodParametersAttribute>
262             implements MethodParametersAttribute {
263         private final List<MethodParameterInfo> parameters;
264 
265         public UnboundMethodParametersAttribute(List<MethodParameterInfo> parameters) {
266             super(Attributes.methodParameters());
267             this.parameters = List.copyOf(parameters);
268         }
269 
270         @Override
271         public List<MethodParameterInfo> parameters() {
272             return parameters;
273         }
274     }
275 
276     public static final class UnboundModuleTargetAttribute
277             extends UnboundAttribute<ModuleTargetAttribute>
278             implements ModuleTargetAttribute {
279         final Utf8Entry moduleTarget;
280 
281         public UnboundModuleTargetAttribute(Utf8Entry moduleTarget) {
282             super(Attributes.moduleTarget());
283             this.moduleTarget = requireNonNull(moduleTarget);
284         }
285 
286         @Override
287         public Utf8Entry targetPlatform() {
288             return moduleTarget;
289         }
290     }
291 
292     public static final class UnboundModuleMainClassAttribute
293             extends UnboundAttribute<ModuleMainClassAttribute>
294             implements ModuleMainClassAttribute {
295         final ClassEntry mainClass;
296 
297         public UnboundModuleMainClassAttribute(ClassEntry mainClass) {
298             super(Attributes.moduleMainClass());
299             this.mainClass = requireNonNull(mainClass);
300         }
301 
302         @Override
303         public ClassEntry mainClass() {
304             return mainClass;
305         }
306     }
307 
308     public static final class UnboundModuleHashesAttribute
309             extends UnboundAttribute<ModuleHashesAttribute>
310             implements ModuleHashesAttribute {
311         private final Utf8Entry algorithm;
312         private final List<ModuleHashInfo> hashes;
313 
314         public UnboundModuleHashesAttribute(Utf8Entry algorithm, List<ModuleHashInfo> hashes) {
315             super(Attributes.moduleHashes());
316             this.algorithm = requireNonNull(algorithm);
317             this.hashes = List.copyOf(hashes);
318         }
319 
320         @Override
321         public Utf8Entry algorithm() {
322             return algorithm;
323         }
324 
325         @Override
326         public List<ModuleHashInfo> hashes() {
327             return hashes;
328         }
329     }
330 
331     public static final class UnboundModulePackagesAttribute
332             extends UnboundAttribute<ModulePackagesAttribute>
333             implements ModulePackagesAttribute {
334         private final Collection<PackageEntry> packages;
335 
336         public UnboundModulePackagesAttribute(Collection<PackageEntry> packages) {
337             super(Attributes.modulePackages());
338             this.packages = List.copyOf(packages);
339         }
340 
341         @Override
342         public List<PackageEntry> packages() {
343             return List.copyOf(packages);
344         }
345     }
346 
347     public static final class UnboundModuleResolutionAttribute
348             extends UnboundAttribute<ModuleResolutionAttribute>
349             implements ModuleResolutionAttribute {
350         private final int resolutionFlags;
351 
352         public UnboundModuleResolutionAttribute(int flags) {
353             super(Attributes.moduleResolution());
354             resolutionFlags = flags;
355         }
356 
357         @Override
358         public int resolutionFlags() {
359             return resolutionFlags;
360         }
361     }
362 
363     public static final class UnboundPermittedSubclassesAttribute
364             extends UnboundAttribute<PermittedSubclassesAttribute>
365             implements PermittedSubclassesAttribute {
366         private final List<ClassEntry> permittedSubclasses;
367 
368         public UnboundPermittedSubclassesAttribute(List<ClassEntry> permittedSubclasses) {
369             super(Attributes.permittedSubclasses());
370             this.permittedSubclasses = List.copyOf(permittedSubclasses);
371         }
372 
373         @Override
374         public List<ClassEntry> permittedSubclasses() {
375             return permittedSubclasses;
376         }
377     }
378 
379     public static final class UnboundLoadableDescriptorsAttribute
380             extends UnboundAttribute<LoadableDescriptorsAttribute>
381             implements LoadableDescriptorsAttribute {
382         private final List<Utf8Entry> loadableDescriptors;
383 
384         public UnboundLoadableDescriptorsAttribute(List<Utf8Entry> loadableDescriptors) {
385             super(Attributes.loadableDescriptors());
386             this.loadableDescriptors = List.copyOf(loadableDescriptors);
387         }
388 
389         @Override
390         public List<Utf8Entry> loadableDescriptors() {
391             return loadableDescriptors;
392         }
393     }
394 
395     public static final class UnboundNestMembersAttribute
396             extends UnboundAttribute<NestMembersAttribute>
397             implements NestMembersAttribute {
398         private final List<ClassEntry> memberEntries;
399 
400         public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
401             super(Attributes.nestMembers());
402             this.memberEntries = List.copyOf(memberEntries);
403         }
404 
405         @Override
406         public List<ClassEntry> nestMembers() {
407             return memberEntries;
408         }
409     }
410 
411     public static final class UnboundNestHostAttribute
412             extends UnboundAttribute<NestHostAttribute>
413             implements NestHostAttribute {
414         private final ClassEntry hostEntry;
415 
416         public UnboundNestHostAttribute(ClassEntry hostEntry) {
417             super(Attributes.nestHost());
418             this.hostEntry = requireNonNull(hostEntry);
419         }
420 
421         @Override
422         public ClassEntry nestHost() {
423             return hostEntry;
424         }
425     }
426 
427     public static final class UnboundCompilationIDAttribute
428             extends UnboundAttribute<CompilationIDAttribute>
429             implements CompilationIDAttribute {
430         private final Utf8Entry idEntry;
431 
432         public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
433             super(Attributes.compilationId());
434             this.idEntry = requireNonNull(idEntry);
435         }
436 
437         @Override
438         public Utf8Entry compilationId() {
439             return idEntry;
440         }
441     }
442 
443     public static final class UnboundSourceIDAttribute
444             extends UnboundAttribute<SourceIDAttribute>
445             implements SourceIDAttribute {
446         private final Utf8Entry idEntry;
447 
448         public UnboundSourceIDAttribute(Utf8Entry idEntry) {
449             super(Attributes.sourceId());
450             this.idEntry = requireNonNull(idEntry);
451         }
452 
453         @Override
454         public Utf8Entry sourceId() {
455             return idEntry;
456         }
457     }
458 
459     public static final class UnboundSourceDebugExtensionAttribute
460         extends UnboundAttribute<SourceDebugExtensionAttribute>
461             implements SourceDebugExtensionAttribute {
462         private final byte[] contents;
463 
464         public UnboundSourceDebugExtensionAttribute(byte[] contents) {
465             super(Attributes.sourceDebugExtension());
466             this.contents = requireNonNull(contents);
467         }
468 
469         @Override
470         public byte[] contents() {
471             return contents;
472         }
473     }
474 
475     public static final class UnboundCharacterRangeTableAttribute
476         extends UnboundAttribute<CharacterRangeTableAttribute>
477             implements CharacterRangeTableAttribute {
478         private final List<CharacterRangeInfo> ranges;
479 
480         public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
481             super(Attributes.characterRangeTable());
482             this.ranges = List.copyOf(ranges);
483         }
484 
485         @Override
486         public List<CharacterRangeInfo> characterRangeTable() {
487             return ranges;
488         }
489     }
490 
491     public static final class UnboundLineNumberTableAttribute
492         extends UnboundAttribute<LineNumberTableAttribute>
493             implements LineNumberTableAttribute {
494         private final List<LineNumberInfo> lines;
495 
496         public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
497             super(Attributes.lineNumberTable());
498             this.lines = List.copyOf(lines);
499         }
500 
501         @Override
502         public List<LineNumberInfo> lineNumbers() {
503             return lines;
504         }
505     }
506 
507     public static final class UnboundLocalVariableTableAttribute
508         extends UnboundAttribute<LocalVariableTableAttribute>
509             implements LocalVariableTableAttribute {
510         private final List<LocalVariableInfo> locals;
511 
512         public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
513             super(Attributes.localVariableTable());
514             this.locals = List.copyOf(locals);
515         }
516 
517         @Override
518         public List<LocalVariableInfo> localVariables() {
519             return locals;
520         }
521     }
522 
523     public static final class UnboundLocalVariableTypeTableAttribute
524         extends UnboundAttribute<LocalVariableTypeTableAttribute>
525             implements LocalVariableTypeTableAttribute {
526         private final List<LocalVariableTypeInfo> locals;
527 
528         public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
529             super(Attributes.localVariableTypeTable());
530             this.locals = List.copyOf(locals);
531         }
532 
533         @Override
534         public List<LocalVariableTypeInfo> localVariableTypes() {
535             return locals;
536         }
537     }
538 
539     public static final class UnboundRuntimeVisibleAnnotationsAttribute
540             extends UnboundAttribute<RuntimeVisibleAnnotationsAttribute>
541             implements RuntimeVisibleAnnotationsAttribute {
542         private final List<Annotation> elements;
543 
544         public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
545             super(Attributes.runtimeVisibleAnnotations());
546             this.elements = List.copyOf(elements);
547         }
548 
549         @Override
550         public List<Annotation> annotations() {
551             return elements;
552         }
553     }
554 
555     public static final class UnboundRuntimeInvisibleAnnotationsAttribute
556             extends UnboundAttribute<RuntimeInvisibleAnnotationsAttribute>
557             implements RuntimeInvisibleAnnotationsAttribute {
558         private final List<Annotation> elements;
559 
560         public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
561             super(Attributes.runtimeInvisibleAnnotations());
562             this.elements = List.copyOf(elements);
563         }
564 
565         @Override
566         public List<Annotation> annotations() {
567             return elements;
568         }
569     }
570 
571     public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute
572             extends UnboundAttribute<RuntimeVisibleParameterAnnotationsAttribute>
573             implements RuntimeVisibleParameterAnnotationsAttribute {
574         private final List<List<Annotation>> elements;
575 
576         public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
577             super(Attributes.runtimeVisibleParameterAnnotations());
578             // deep copy
579             var array = elements.toArray().clone();
580             for (int i = 0; i < array.length; i++) {
581                 array[i] = List.copyOf((List<?>) array[i]);
582             }
583 
584             this.elements = SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
585         }
586 
587         @Override
588         public List<List<Annotation>> parameterAnnotations() {
589             return elements;
590         }
591     }
592 
593     public static final class UnboundRuntimeInvisibleParameterAnnotationsAttribute
594             extends UnboundAttribute<RuntimeInvisibleParameterAnnotationsAttribute>
595             implements RuntimeInvisibleParameterAnnotationsAttribute {
596         private final List<List<Annotation>> elements;
597 
598         public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
599             super(Attributes.runtimeInvisibleParameterAnnotations());
600             // deep copy
601             var array = elements.toArray().clone();
602             for (int i = 0; i < array.length; i++) {
603                 array[i] = List.copyOf((List<?>) array[i]);
604             }
605 
606             this.elements = SharedSecrets.getJavaUtilCollectionAccess().listFromTrustedArray(array);
607         }
608 
609         @Override
610         public List<List<Annotation>> parameterAnnotations() {
611             return elements;
612         }
613     }
614 
615     public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute
616             extends UnboundAttribute<RuntimeVisibleTypeAnnotationsAttribute>
617             implements RuntimeVisibleTypeAnnotationsAttribute {
618         private final List<TypeAnnotation> elements;
619 
620         public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
621             super(Attributes.runtimeVisibleTypeAnnotations());
622             this.elements = List.copyOf(elements);
623         }
624 
625         @Override
626         public List<TypeAnnotation> annotations() {
627             return elements;
628         }
629     }
630 
631     public static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute
632             extends UnboundAttribute<RuntimeInvisibleTypeAnnotationsAttribute>
633             implements RuntimeInvisibleTypeAnnotationsAttribute {
634         private final List<TypeAnnotation> elements;
635 
636         public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
637             super(Attributes.runtimeInvisibleTypeAnnotations());
638             this.elements = List.copyOf(elements);
639         }
640 
641         @Override
642         public List<TypeAnnotation> annotations() {
643             return elements;
644         }
645     }
646 
647     public record UnboundCharacterRangeInfo(int startPc, int endPc,
648                                             int characterRangeStart,
649                                             int characterRangeEnd,
650                                             int flags)
651             implements CharacterRangeInfo { }
652 
653     public record UnboundInnerClassInfo(ClassEntry innerClass,
654                                         Optional<ClassEntry> outerClass,
655                                         Optional<Utf8Entry> innerName,
656                                         int flagsMask)
657             implements InnerClassInfo {
658         public UnboundInnerClassInfo {
659             requireNonNull(innerClass);
660             requireNonNull(outerClass);
661             requireNonNull(innerName);
662         }
663     }
664 
665     public record UnboundLineNumberInfo(int startPc, int lineNumber)
666             implements LineNumberInfo { }
667 
668     public record UnboundLocalVariableInfo(int startPc, int length,
669                                            Utf8Entry name,
670                                            Utf8Entry type,
671                                            int slot)
672             implements LocalVariableInfo {
673         public UnboundLocalVariableInfo {
674             requireNonNull(name);
675             requireNonNull(type);
676         }
677     }
678 
679     public record UnboundLocalVariableTypeInfo(int startPc, int length,
680                                                Utf8Entry name,
681                                                Utf8Entry signature,
682                                                int slot)
683             implements LocalVariableTypeInfo {
684         public UnboundLocalVariableTypeInfo {
685             requireNonNull(name);
686             requireNonNull(signature);
687         }
688     }
689 
690     public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask)
691             implements MethodParameterInfo {
692         public UnboundMethodParameterInfo {
693             requireNonNull(name);
694         }
695     }
696 
697     public record UnboundModuleExportInfo(PackageEntry exportedPackage,
698                                           int exportsFlagsMask,
699                                           List<ModuleEntry> exportsTo)
700             implements ModuleExportInfo {
701         public UnboundModuleExportInfo {
702             requireNonNull(exportedPackage);
703             exportsTo = List.copyOf(exportsTo);
704         }
705     }
706 
707     public record UnboundModuleHashInfo(ModuleEntry moduleName,
708                                         byte[] hash) implements ModuleHashInfo {
709         public UnboundModuleHashInfo {
710             requireNonNull(moduleName);
711             requireNonNull(hash);
712         }
713     }
714 
715     public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
716                                         List<ModuleEntry> opensTo)
717             implements ModuleOpenInfo {
718         public UnboundModuleOpenInfo {
719             requireNonNull(openedPackage);
720             opensTo = List.copyOf(opensTo);
721         }
722     }
723 
724     public record UnboundModuleProvideInfo(ClassEntry provides,
725                                            List<ClassEntry> providesWith)
726             implements ModuleProvideInfo {
727         public UnboundModuleProvideInfo {
728             requireNonNull(provides);
729             providesWith = List.copyOf(providesWith);
730         }
731     }
732 
733     public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask,
734                                             Optional<Utf8Entry> requiresVersion)
735             implements ModuleRequireInfo {
736         public UnboundModuleRequiresInfo {
737             requireNonNull(requires);
738             requireNonNull(requiresVersion);
739         }
740     }
741 
742     public record UnboundRecordComponentInfo(Utf8Entry name,
743                                              Utf8Entry descriptor,
744                                              List<Attribute<?>> attributes)
745             implements RecordComponentInfo {
746         public UnboundRecordComponentInfo {
747             requireNonNull(name);
748             requireNonNull(descriptor);
749             attributes = List.copyOf(attributes);
750         }
751     }
752 
753     public record UnboundTypeAnnotation(TargetInfo targetInfo,
754                                         List<TypePathComponent> targetPath,
755                                         Annotation annotation) implements TypeAnnotation {
756 
757         public UnboundTypeAnnotation {
758             requireNonNull(targetInfo);
759             targetPath = List.copyOf(targetPath);
760             requireNonNull(annotation);
761         }
762     }
763 
764     public record TypePathComponentImpl(TypeAnnotation.TypePathComponent.Kind typePathKind, int typeArgumentIndex)
765             implements TypeAnnotation.TypePathComponent {}
766 
767     public static final class UnboundModuleAttribute extends UnboundAttribute<ModuleAttribute> implements ModuleAttribute {
768         private final ModuleEntry moduleName;
769         private final int moduleFlags;
770         private final Utf8Entry moduleVersion;
771         private final List<ModuleRequireInfo> requires;
772         private final List<ModuleExportInfo> exports;
773         private final List<ModuleOpenInfo> opens;
774         private final List<ClassEntry> uses;
775         private final List<ModuleProvideInfo> provides;
776 
777         public UnboundModuleAttribute(ModuleEntry moduleName,
778                                       int moduleFlags,
779                                       Utf8Entry moduleVersion,
780                                       Collection<ModuleRequireInfo> requires,
781                                       Collection<ModuleExportInfo> exports,
782                                       Collection<ModuleOpenInfo> opens,
783                                       Collection<ClassEntry> uses,
784                                       Collection<ModuleProvideInfo> provides)
785         {
786             super(Attributes.module());
787             this.moduleName = requireNonNull(moduleName);
788             this.moduleFlags = moduleFlags;
789             this.moduleVersion = moduleVersion;
790             this.requires = List.copyOf(requires);
791             this.exports = List.copyOf(exports);
792             this.opens = List.copyOf(opens);
793             this.uses = List.copyOf(uses);
794             this.provides = List.copyOf(provides);
795         }
796 
797         @Override
798         public ModuleEntry moduleName() {
799             return moduleName;
800         }
801 
802         @Override
803         public int moduleFlagsMask() {
804             return moduleFlags;
805         }
806 
807         @Override
808         public Optional<Utf8Entry> moduleVersion() {
809             return Optional.ofNullable(moduleVersion);
810         }
811 
812         @Override
813         public List<ModuleRequireInfo> requires() {
814             return requires;
815         }
816 
817         @Override
818         public List<ModuleExportInfo> exports() {
819             return exports;
820         }
821 
822         @Override
823         public List<ModuleOpenInfo> opens() {
824             return opens;
825         }
826 
827         @Override
828         public List<ClassEntry> uses() {
829             return uses;
830         }
831 
832         @Override
833         public List<ModuleProvideInfo> provides() {
834             return provides;
835         }
836     }
837 
838     public abstract static non-sealed class AdHocAttribute<T extends Attribute<T>>
839             extends UnboundAttribute<T> {
840 
841         public AdHocAttribute(AttributeMapper<T> mapper) {
842             super(mapper);
843         }
844 
845         public abstract void writeBody(BufWriterImpl b);
846 
847         @Override
848         public void writeTo(BufWriterImpl b) {
849             b.writeIndex(b.constantPool().utf8Entry(mapper.name()));
850             int lengthIndex = b.skip(4);
851             writeBody(b);
852             int written = b.size() - lengthIndex - 4;
853             b.patchInt(lengthIndex, written);
854         }
855     }
856 
857     public static final class EmptyBootstrapAttribute
858             extends UnboundAttribute<BootstrapMethodsAttribute>
859             implements BootstrapMethodsAttribute {
860         public EmptyBootstrapAttribute() {
861             super(Attributes.bootstrapMethods());
862         }
863 
864         @Override
865         public int bootstrapMethodsSize() {
866             return 0;
867         }
868 
869         @Override
870         public List<BootstrapMethodEntry> bootstrapMethods() {
871             return List.of();
872         }
873     }
874 }