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