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