1 /*
  2  * Copyright (c) 2022, 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.AnnotationElement;
 33 import java.lang.classfile.AnnotationValue;
 34 import java.lang.classfile.Attribute;
 35 import java.lang.classfile.AttributeMapper;
 36 import java.lang.classfile.Attributes;
 37 import java.lang.classfile.BootstrapMethodEntry;
 38 import java.lang.classfile.BufWriter;
 39 import java.lang.classfile.constantpool.ClassEntry;
 40 import java.lang.classfile.Label;
 41 import java.lang.classfile.TypeAnnotation;
 42 import java.lang.classfile.attribute.AnnotationDefaultAttribute;
 43 import java.lang.classfile.attribute.BootstrapMethodsAttribute;
 44 import java.lang.classfile.attribute.CharacterRangeInfo;
 45 import java.lang.classfile.attribute.CharacterRangeTableAttribute;
 46 import java.lang.classfile.attribute.CompilationIDAttribute;
 47 import java.lang.classfile.attribute.ConstantValueAttribute;
 48 import java.lang.classfile.attribute.DeprecatedAttribute;
 49 import java.lang.classfile.attribute.EnclosingMethodAttribute;
 50 import java.lang.classfile.attribute.ExceptionsAttribute;
 51 import java.lang.classfile.attribute.InnerClassInfo;
 52 import java.lang.classfile.attribute.InnerClassesAttribute;
 53 import java.lang.classfile.attribute.LineNumberInfo;
 54 import java.lang.classfile.attribute.LineNumberTableAttribute;
 55 import java.lang.classfile.attribute.LoadableDescriptorsAttribute;
 56 import java.lang.classfile.attribute.LocalVariableInfo;
 57 import java.lang.classfile.attribute.LocalVariableTableAttribute;
 58 import java.lang.classfile.attribute.LocalVariableTypeInfo;
 59 import java.lang.classfile.attribute.LocalVariableTypeTableAttribute;
 60 import java.lang.classfile.attribute.MethodParameterInfo;
 61 import java.lang.classfile.attribute.MethodParametersAttribute;
 62 import java.lang.classfile.attribute.ModuleAttribute;
 63 import java.lang.classfile.attribute.ModuleExportInfo;
 64 import java.lang.classfile.attribute.ModuleHashInfo;
 65 import java.lang.classfile.attribute.ModuleHashesAttribute;
 66 import java.lang.classfile.attribute.ModuleMainClassAttribute;
 67 import java.lang.classfile.attribute.ModuleOpenInfo;
 68 import java.lang.classfile.attribute.ModulePackagesAttribute;
 69 import java.lang.classfile.attribute.ModuleProvideInfo;
 70 import java.lang.classfile.attribute.ModuleRequireInfo;
 71 import java.lang.classfile.attribute.ModuleResolutionAttribute;
 72 import java.lang.classfile.attribute.ModuleTargetAttribute;
 73 import java.lang.classfile.attribute.NestHostAttribute;
 74 import java.lang.classfile.attribute.NestMembersAttribute;
 75 import java.lang.classfile.attribute.PermittedSubclassesAttribute;
 76 import java.lang.classfile.attribute.RecordAttribute;
 77 import java.lang.classfile.attribute.RecordComponentInfo;
 78 import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
 79 import java.lang.classfile.attribute.RuntimeInvisibleParameterAnnotationsAttribute;
 80 import java.lang.classfile.attribute.RuntimeInvisibleTypeAnnotationsAttribute;
 81 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
 82 import java.lang.classfile.attribute.RuntimeVisibleParameterAnnotationsAttribute;
 83 import java.lang.classfile.attribute.RuntimeVisibleTypeAnnotationsAttribute;
 84 import java.lang.classfile.attribute.SignatureAttribute;
 85 import java.lang.classfile.attribute.SourceDebugExtensionAttribute;
 86 import java.lang.classfile.attribute.SourceFileAttribute;
 87 import java.lang.classfile.attribute.SourceIDAttribute;
 88 import java.lang.classfile.attribute.StackMapTableAttribute;
 89 import java.lang.classfile.attribute.StackMapFrameInfo;
 90 import java.lang.classfile.attribute.SyntheticAttribute;
 91 import java.lang.classfile.constantpool.ConstantValueEntry;
 92 import java.lang.classfile.constantpool.ModuleEntry;
 93 import java.lang.classfile.constantpool.NameAndTypeEntry;
 94 import java.lang.classfile.constantpool.PackageEntry;
 95 import java.lang.classfile.constantpool.Utf8Entry;
 96 
 97 public abstract sealed class UnboundAttribute<T extends Attribute<T>>
 98         extends AbstractElement
 99         implements Attribute<T> {
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(BufWriter 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 UnboundLoadableDescriptorsAttribute
434             extends UnboundAttribute<LoadableDescriptorsAttribute>
435             implements LoadableDescriptorsAttribute {
436         private final List<Utf8Entry> loadableDescriptors;
437 
438         public UnboundLoadableDescriptorsAttribute(List<Utf8Entry> loadableDescriptors) {
439             super(Attributes.loadableDescriptors());
440             this.loadableDescriptors = List.copyOf(loadableDescriptors);
441         }
442 
443         @Override
444         public List<Utf8Entry> loadableDescriptors() {
445             return loadableDescriptors;
446         }
447     }
448 
449     public static final class UnboundNestMembersAttribute
450             extends UnboundAttribute<NestMembersAttribute>
451             implements NestMembersAttribute {
452         private final List<ClassEntry> memberEntries;
453 
454         public UnboundNestMembersAttribute(List<ClassEntry> memberEntries) {
455             super(Attributes.nestMembers());
456             this.memberEntries = List.copyOf(memberEntries);
457         }
458 
459         @Override
460         public List<ClassEntry> nestMembers() {
461             return memberEntries;
462         }
463     }
464 
465     public static final class UnboundNestHostAttribute
466             extends UnboundAttribute<NestHostAttribute>
467             implements NestHostAttribute {
468         private final ClassEntry hostEntry;
469 
470         public UnboundNestHostAttribute(ClassEntry hostEntry) {
471             super(Attributes.nestHost());
472             this.hostEntry = hostEntry;
473         }
474 
475         @Override
476         public ClassEntry nestHost() {
477             return hostEntry;
478         }
479     }
480 
481     public static final class UnboundCompilationIDAttribute
482             extends UnboundAttribute<CompilationIDAttribute>
483             implements CompilationIDAttribute {
484         private final Utf8Entry idEntry;
485 
486         public UnboundCompilationIDAttribute(Utf8Entry idEntry) {
487             super(Attributes.compilationId());
488             this.idEntry = idEntry;
489         }
490 
491         @Override
492         public Utf8Entry compilationId() {
493             return idEntry;
494         }
495     }
496 
497     public static final class UnboundSourceIDAttribute
498             extends UnboundAttribute<SourceIDAttribute>
499             implements SourceIDAttribute {
500         private final Utf8Entry idEntry;
501 
502         public UnboundSourceIDAttribute(Utf8Entry idEntry) {
503             super(Attributes.sourceId());
504             this.idEntry = idEntry;
505         }
506 
507         @Override
508         public Utf8Entry sourceId() {
509             return idEntry;
510         }
511     }
512 
513     public static final class UnboundSourceDebugExtensionAttribute
514         extends UnboundAttribute<SourceDebugExtensionAttribute>
515             implements SourceDebugExtensionAttribute {
516         private final byte[] contents;
517 
518         public UnboundSourceDebugExtensionAttribute(byte[] contents) {
519             super(Attributes.sourceDebugExtension());
520             this.contents = contents;
521         }
522 
523         @Override
524         public byte[] contents() {
525             return contents;
526         }
527     }
528 
529     public static final class UnboundCharacterRangeTableAttribute
530         extends UnboundAttribute<CharacterRangeTableAttribute>
531             implements CharacterRangeTableAttribute {
532         private final List<CharacterRangeInfo> ranges;
533 
534         public UnboundCharacterRangeTableAttribute(List<CharacterRangeInfo> ranges) {
535             super(Attributes.characterRangeTable());
536             this.ranges = List.copyOf(ranges);
537         }
538 
539         @Override
540         public List<CharacterRangeInfo> characterRangeTable() {
541             return ranges;
542         }
543     }
544 
545     public static final class UnboundLineNumberTableAttribute
546         extends UnboundAttribute<LineNumberTableAttribute>
547             implements LineNumberTableAttribute {
548         private final List<LineNumberInfo> lines;
549 
550         public UnboundLineNumberTableAttribute(List<LineNumberInfo> lines) {
551             super(Attributes.lineNumberTable());
552             this.lines = List.copyOf(lines);
553         }
554 
555         @Override
556         public List<LineNumberInfo> lineNumbers() {
557             return lines;
558         }
559     }
560 
561     public static final class UnboundLocalVariableTableAttribute
562         extends UnboundAttribute<LocalVariableTableAttribute>
563             implements LocalVariableTableAttribute {
564         private final List<LocalVariableInfo> locals;
565 
566         public UnboundLocalVariableTableAttribute(List<LocalVariableInfo> locals) {
567             super(Attributes.localVariableTable());
568             this.locals = List.copyOf(locals);
569         }
570 
571         @Override
572         public List<LocalVariableInfo> localVariables() {
573             return locals;
574         }
575     }
576 
577     public static final class UnboundLocalVariableTypeTableAttribute
578         extends UnboundAttribute<LocalVariableTypeTableAttribute>
579             implements LocalVariableTypeTableAttribute {
580         private final List<LocalVariableTypeInfo> locals;
581 
582         public UnboundLocalVariableTypeTableAttribute(List<LocalVariableTypeInfo> locals) {
583             super(Attributes.localVariableTypeTable());
584             this.locals = List.copyOf(locals);
585         }
586 
587         @Override
588         public List<LocalVariableTypeInfo> localVariableTypes() {
589             return locals;
590         }
591     }
592 
593     public static final class UnboundRuntimeVisibleAnnotationsAttribute
594             extends UnboundAttribute<RuntimeVisibleAnnotationsAttribute>
595             implements RuntimeVisibleAnnotationsAttribute {
596         private final List<Annotation> elements;
597 
598         public UnboundRuntimeVisibleAnnotationsAttribute(List<Annotation> elements) {
599             super(Attributes.runtimeVisibleAnnotations());
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 UnboundRuntimeInvisibleAnnotationsAttribute
610             extends UnboundAttribute<RuntimeInvisibleAnnotationsAttribute>
611             implements RuntimeInvisibleAnnotationsAttribute {
612         private final List<Annotation> elements;
613 
614         public UnboundRuntimeInvisibleAnnotationsAttribute(List<Annotation> elements) {
615             super(Attributes.runtimeInvisibleAnnotations());
616             this.elements = List.copyOf(elements);
617         }
618 
619         @Override
620         public List<Annotation> annotations() {
621             return elements;
622         }
623     }
624 
625     public static final class UnboundRuntimeVisibleParameterAnnotationsAttribute
626             extends UnboundAttribute<RuntimeVisibleParameterAnnotationsAttribute>
627             implements RuntimeVisibleParameterAnnotationsAttribute {
628         private final List<List<Annotation>> elements;
629 
630         public UnboundRuntimeVisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
631             super(Attributes.runtimeVisibleParameterAnnotations());
632             this.elements = List.copyOf(elements);
633         }
634 
635         @Override
636         public List<List<Annotation>> parameterAnnotations() {
637             return elements;
638         }
639     }
640 
641     public static final class UnboundRuntimeInvisibleParameterAnnotationsAttribute
642             extends UnboundAttribute<RuntimeInvisibleParameterAnnotationsAttribute>
643             implements RuntimeInvisibleParameterAnnotationsAttribute {
644         private final List<List<Annotation>> elements;
645 
646         public UnboundRuntimeInvisibleParameterAnnotationsAttribute(List<List<Annotation>> elements) {
647             super(Attributes.runtimeInvisibleParameterAnnotations());
648             this.elements = List.copyOf(elements);
649         }
650 
651         @Override
652         public List<List<Annotation>> parameterAnnotations() {
653             return elements;
654         }
655     }
656 
657     public static final class UnboundRuntimeVisibleTypeAnnotationsAttribute
658             extends UnboundAttribute<RuntimeVisibleTypeAnnotationsAttribute>
659             implements RuntimeVisibleTypeAnnotationsAttribute {
660         private final List<TypeAnnotation> elements;
661 
662         public UnboundRuntimeVisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
663             super(Attributes.runtimeVisibleTypeAnnotations());
664             this.elements = List.copyOf(elements);
665         }
666 
667         @Override
668         public List<TypeAnnotation> annotations() {
669             return elements;
670         }
671     }
672 
673     public static final class UnboundRuntimeInvisibleTypeAnnotationsAttribute
674             extends UnboundAttribute<RuntimeInvisibleTypeAnnotationsAttribute>
675             implements RuntimeInvisibleTypeAnnotationsAttribute {
676         private final List<TypeAnnotation> elements;
677 
678         public UnboundRuntimeInvisibleTypeAnnotationsAttribute(List<TypeAnnotation> elements) {
679             super(Attributes.runtimeInvisibleTypeAnnotations());
680             this.elements = List.copyOf(elements);
681         }
682 
683         @Override
684         public List<TypeAnnotation> annotations() {
685             return elements;
686         }
687     }
688 
689     public record UnboundCharacterRangeInfo(int startPc, int endPc,
690                                             int characterRangeStart,
691                                             int characterRangeEnd,
692                                             int flags)
693             implements CharacterRangeInfo { }
694 
695     public record UnboundInnerClassInfo(ClassEntry innerClass,
696                                         Optional<ClassEntry> outerClass,
697                                         Optional<Utf8Entry> innerName,
698                                         int flagsMask)
699             implements InnerClassInfo {}
700 
701     public record UnboundLineNumberInfo(int startPc, int lineNumber)
702             implements LineNumberInfo { }
703 
704     public record UnboundLocalVariableInfo(int startPc, int length,
705                                            Utf8Entry name,
706                                            Utf8Entry type,
707                                            int slot)
708             implements LocalVariableInfo { }
709 
710     public record UnboundLocalVariableTypeInfo(int startPc, int length,
711                                                Utf8Entry name,
712                                                Utf8Entry signature,
713                                                int slot)
714             implements LocalVariableTypeInfo { }
715 
716     public record UnboundMethodParameterInfo(Optional<Utf8Entry> name, int flagsMask)
717             implements MethodParameterInfo {}
718 
719     public record UnboundModuleExportInfo(PackageEntry exportedPackage,
720                                           int exportsFlagsMask,
721                                           List<ModuleEntry> exportsTo)
722             implements ModuleExportInfo {
723         public UnboundModuleExportInfo(PackageEntry exportedPackage, int exportsFlagsMask,
724                                        List<ModuleEntry> exportsTo) {
725             this.exportedPackage = exportedPackage;
726             this.exportsFlagsMask = exportsFlagsMask;
727             this.exportsTo = List.copyOf(exportsTo);
728         }
729     }
730 
731     public record UnboundModuleHashInfo(ModuleEntry moduleName,
732                                         byte[] hash) implements ModuleHashInfo { }
733 
734     public record UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
735                                         List<ModuleEntry> opensTo)
736             implements ModuleOpenInfo {
737         public UnboundModuleOpenInfo(PackageEntry openedPackage, int opensFlagsMask,
738                                      List<ModuleEntry> opensTo) {
739             this.openedPackage = openedPackage;
740             this.opensFlagsMask = opensFlagsMask;
741             this.opensTo = List.copyOf(opensTo);
742         }
743     }
744 
745     public record UnboundModuleProvideInfo(ClassEntry provides,
746                                            List<ClassEntry> providesWith)
747             implements ModuleProvideInfo {
748         public UnboundModuleProvideInfo(ClassEntry provides, List<ClassEntry> providesWith) {
749             this.provides = provides;
750             this.providesWith = List.copyOf(providesWith);
751         }
752     }
753 
754     public record UnboundModuleRequiresInfo(ModuleEntry requires, int requiresFlagsMask,
755                                             Optional<Utf8Entry> requiresVersion)
756             implements ModuleRequireInfo {}
757 
758     public record UnboundRecordComponentInfo(Utf8Entry name,
759                                              Utf8Entry descriptor,
760                                              List<Attribute<?>> attributes)
761             implements RecordComponentInfo {
762         public UnboundRecordComponentInfo(Utf8Entry name, Utf8Entry descriptor, List<Attribute<?>> attributes) {
763             this.name = name;
764             this.descriptor = descriptor;
765             this.attributes = List.copyOf(attributes);
766         }
767     }
768 
769     public record UnboundTypeAnnotation(TargetInfo targetInfo,
770                                         List<TypePathComponent> targetPath,
771                                         Utf8Entry className,
772                                         List<AnnotationElement> elements) implements TypeAnnotation {
773 
774         public UnboundTypeAnnotation(TargetInfo targetInfo, List<TypePathComponent> targetPath,
775                                      Utf8Entry className, List<AnnotationElement> elements) {
776             this.targetInfo = targetInfo;
777             this.targetPath = List.copyOf(targetPath);
778             this.className = className;
779             this.elements = List.copyOf(elements);
780         }
781 
782         private int labelToBci(LabelContext lr, Label label) {
783             //helper method to avoid NPE
784             if (lr == null) throw new IllegalArgumentException("Illegal targetType '%s' in TypeAnnotation outside of Code attribute".formatted(targetInfo.targetType()));
785             return lr.labelToBci(label);
786         }
787 
788         @Override
789         public void writeTo(BufWriter buf) {
790             LabelContext lr = ((BufWriterImpl) buf).labelContext();
791             // target_type
792             buf.writeU1(targetInfo.targetType().targetTypeValue());
793 
794             // target_info
795             switch (targetInfo) {
796                 case TypeParameterTarget tpt -> buf.writeU1(tpt.typeParameterIndex());
797                 case SupertypeTarget st -> buf.writeU2(st.supertypeIndex());
798                 case TypeParameterBoundTarget tpbt -> {
799                     buf.writeU1(tpbt.typeParameterIndex());
800                     buf.writeU1(tpbt.boundIndex());
801                 }
802                 case EmptyTarget et -> {
803                     // nothing to write
804                 }
805                 case FormalParameterTarget fpt -> buf.writeU1(fpt.formalParameterIndex());
806                 case ThrowsTarget tt -> buf.writeU2(tt.throwsTargetIndex());
807                 case LocalVarTarget lvt -> {
808                     buf.writeU2(lvt.table().size());
809                     for (var e : lvt.table()) {
810                         int startPc = labelToBci(lr, e.startLabel());
811                         buf.writeU2(startPc);
812                         buf.writeU2(labelToBci(lr, e.endLabel()) - startPc);
813                         buf.writeU2(e.index());
814                     }
815                 }
816                 case CatchTarget ct -> buf.writeU2(ct.exceptionTableIndex());
817                 case OffsetTarget ot -> buf.writeU2(labelToBci(lr, ot.target()));
818                 case TypeArgumentTarget tat -> {
819                     buf.writeU2(labelToBci(lr, tat.target()));
820                     buf.writeU1(tat.typeArgumentIndex());
821                 }
822             }
823 
824             // target_path
825             buf.writeU1(targetPath().size());
826             for (TypePathComponent component : targetPath()) {
827                 buf.writeU1(component.typePathKind().tag());
828                 buf.writeU1(component.typeArgumentIndex());
829             }
830 
831             // type_index
832             buf.writeIndex(className);
833 
834             // element_value_pairs
835             buf.writeU2(elements.size());
836             for (AnnotationElement pair : elements()) {
837                 buf.writeIndex(pair.name());
838                 pair.value().writeTo(buf);
839             }
840         }
841     }
842 
843     public record TypePathComponentImpl(TypeAnnotation.TypePathComponent.Kind typePathKind, int typeArgumentIndex)
844             implements TypeAnnotation.TypePathComponent {}
845 
846     public static final class UnboundModuleAttribute extends UnboundAttribute<ModuleAttribute> implements ModuleAttribute {
847         private final ModuleEntry moduleName;
848         private final int moduleFlags;
849         private final Utf8Entry moduleVersion;
850         private final List<ModuleRequireInfo> requires;
851         private final List<ModuleExportInfo> exports;
852         private final List<ModuleOpenInfo> opens;
853         private final List<ClassEntry> uses;
854         private final List<ModuleProvideInfo> provides;
855 
856         public UnboundModuleAttribute(ModuleEntry moduleName,
857                                       int moduleFlags,
858                                       Utf8Entry moduleVersion,
859                                       Collection<ModuleRequireInfo> requires,
860                                       Collection<ModuleExportInfo> exports,
861                                       Collection<ModuleOpenInfo> opens,
862                                       Collection<ClassEntry> uses,
863                                       Collection<ModuleProvideInfo> provides)
864         {
865             super(Attributes.module());
866             this.moduleName = moduleName;
867             this.moduleFlags = moduleFlags;
868             this.moduleVersion = moduleVersion;
869             this.requires = List.copyOf(requires);
870             this.exports = List.copyOf(exports);
871             this.opens = List.copyOf(opens);
872             this.uses = List.copyOf(uses);
873             this.provides = List.copyOf(provides);
874         }
875 
876         @Override
877         public ModuleEntry moduleName() {
878             return moduleName;
879         }
880 
881         @Override
882         public int moduleFlagsMask() {
883             return moduleFlags;
884         }
885 
886         @Override
887         public Optional<Utf8Entry> moduleVersion() {
888             return Optional.ofNullable(moduleVersion);
889         }
890 
891         @Override
892         public List<ModuleRequireInfo> requires() {
893             return requires;
894         }
895 
896         @Override
897         public List<ModuleExportInfo> exports() {
898             return exports;
899         }
900 
901         @Override
902         public List<ModuleOpenInfo> opens() {
903             return opens;
904         }
905 
906         @Override
907         public List<ClassEntry> uses() {
908             return uses;
909         }
910 
911         @Override
912         public List<ModuleProvideInfo> provides() {
913             return provides;
914         }
915     }
916 
917     public abstract static non-sealed class AdHocAttribute<T extends Attribute<T>>
918             extends UnboundAttribute<T> {
919 
920         public AdHocAttribute(AttributeMapper<T> mapper) {
921             super(mapper);
922         }
923 
924         public abstract void writeBody(BufWriter b);
925 
926         @Override
927         public void writeTo(BufWriter b) {
928             b.writeIndex(b.constantPool().utf8Entry(mapper.name()));
929             b.writeInt(0);
930             int start = b.size();
931             writeBody(b);
932             int written = b.size() - start;
933             b.patchInt(start - 4, 4, written);
934         }
935     }
936 
937     public static final class EmptyBootstrapAttribute
938             extends UnboundAttribute<BootstrapMethodsAttribute>
939             implements BootstrapMethodsAttribute {
940         public EmptyBootstrapAttribute() {
941             super(Attributes.bootstrapMethods());
942         }
943 
944         @Override
945         public int bootstrapMethodsSize() {
946             return 0;
947         }
948 
949         @Override
950         public List<BootstrapMethodEntry> bootstrapMethods() {
951             return List.of();
952         }
953     }
954 }