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