8335905: CompoundElement API cleanup

Reviewed-by: asotona
This commit is contained in:
Chen Liang 2024-07-14 15:01:51 +00:00
parent 6f325db493
commit a9f5e76a65
34 changed files with 73 additions and 82 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -89,7 +89,7 @@ public sealed interface ClassFileBuilder<E extends ClassFileElement, B extends C
B builder = (B) this;
var resolved = transform.resolve(builder);
resolved.startHandler().run();
model.forEachElement(resolved.consumer());
model.forEach(resolved.consumer());
resolved.endHandler().run();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,7 +37,7 @@ import jdk.internal.javac.PreviewFeature;
/**
* Models a classfile. The contents of the classfile can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*
* @since 22

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,8 +36,7 @@ import jdk.internal.javac.PreviewFeature;
/**
* Models the body of a method (the {@code Code} attribute). The instructions
* of the method body are accessed via a streaming view (e.g., {@link
* #elements()}).
* of the method body are accessed via a streaming view.
*
* @since 22
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,7 @@ import jdk.internal.javac.PreviewFeature;
* class. When encountering a {@linkplain CompoundElement}, clients have the
* option to treat the element as a single entity (e.g., an entire method)
* or to traverse the contents of that element with the methods in this class
* (e.g., {@link #elements()}, {@link #forEachElement(Consumer)}, etc.)
* (e.g., {@link #forEach(Consumer)}, etc.)
* @param <E> the element type
*
* @sealedGraph
@ -55,15 +55,8 @@ public sealed interface CompoundElement<E extends ClassFileElement>
* compound element
* @param consumer the handler
*/
void forEachElement(Consumer<E> consumer);
/**
* {@return an {@link Iterable} describing all the elements contained in this
* compound element}
*/
default Iterable<E> elements() {
return elementList();
}
@Override
void forEach(Consumer<? super E> consumer);
/**
* {@return an {@link Iterator} describing all the elements contained in this
@ -71,7 +64,7 @@ public sealed interface CompoundElement<E extends ClassFileElement>
*/
@Override
default Iterator<E> iterator() {
return elements().iterator();
return elementList().iterator();
}
/**
@ -91,7 +84,7 @@ public sealed interface CompoundElement<E extends ClassFileElement>
*/
default List<E> elementList() {
List<E> list = new ArrayList<>();
forEachElement(new Consumer<>() {
forEach(new Consumer<>() {
@Override
public void accept(E e) {
list.add(e);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ import jdk.internal.javac.PreviewFeature;
/**
* Models a field. The contents of the field can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*
* @since 22

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,7 @@ import jdk.internal.javac.PreviewFeature;
/**
* Models a method. The contents of the method can be traversed via
* a streaming view (e.g., {@link #elements()}), or via random access (e.g.,
* a streaming view, or via random access (e.g.,
* {@link #flags()}), or by freely mixing the two.
*
* @since 22

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -45,7 +45,7 @@ public abstract sealed class AbstractUnboundModel<E extends ClassFileElement>
}
@Override
public void forEachElement(Consumer<E> consumer) {
public void forEach(Consumer<? super E> consumer) {
elements.forEach(consumer);
}

View File

@ -201,7 +201,7 @@ public final class BufferedCodeBuilder
builder.withCode(new Consumer<>() {
@Override
public void accept(CodeBuilder cb) {
forEachElement(cb);
forEach(cb);
}
});
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -200,7 +200,7 @@ public final class BufferedMethodBuilder
builder.withMethod(methodName(), methodType(), methodFlags(), new Consumer<>() {
@Override
public void accept(MethodBuilder mb) {
forEachElement(mb);
forEach(mb);
}
});
}

View File

@ -156,7 +156,7 @@ public final class ClassImpl
// ClassModel
@Override
public void forEachElement(Consumer<ClassElement> consumer) {
public void forEach(Consumer<? super ClassElement> consumer) {
consumer.accept(flags());
consumer.accept(ClassFileVersion.of(majorVersion(), minorVersion()));
superclass().ifPresent(new Consumer<ClassEntry>() {

View File

@ -97,12 +97,10 @@ public record ClassRemapperImpl(Function<ClassDesc, ClassDesc> mapFunction) impl
switch (cle) {
case FieldModel fm ->
clb.withField(fm.fieldName().stringValue(), map(
fm.fieldTypeSymbol()), fb ->
fm.forEachElement(asFieldTransform().resolve(fb).consumer()));
fm.fieldTypeSymbol()), fb -> fb.transform(fm, asFieldTransform()));
case MethodModel mm ->
clb.withMethod(mm.methodName().stringValue(), mapMethodDesc(
mm.methodTypeSymbol()), mm.flags().flagsMask(), mb ->
mm.forEachElement(asMethodTransform().resolve(mb).consumer()));
mm.methodTypeSymbol()), mm.flags().flagsMask(), mb -> mb.transform(mm, asMethodTransform()));
case Superclass sc ->
clb.withSuperclass(map(sc.superclassEntry().asSymbol()));
case Interfaces ins ->

View File

@ -27,6 +27,7 @@ package jdk.internal.classfile.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
@ -149,7 +150,7 @@ public final class CodeImpl
new Consumer<CodeBuilder>() {
@Override
public void accept(CodeBuilder cb) {
forEachElement(cb);
forEach(cb);
}
},
(SplitConstantPool)buf.constantPool(),
@ -166,7 +167,8 @@ public final class CodeImpl
}
@Override
public void forEachElement(Consumer<CodeElement> consumer) {
public void forEach(Consumer<? super CodeElement> consumer) {
Objects.requireNonNull(consumer);
inflateMetadata();
boolean doLineNumbers = (lineNumbers != null);
generateCatchTargets(consumer);
@ -329,7 +331,7 @@ public final class CodeImpl
findAttribute(Attributes.runtimeInvisibleTypeAnnotations()).ifPresent(RuntimeInvisibleTypeAnnotationsAttribute::annotations);
}
private void generateCatchTargets(Consumer<CodeElement> consumer) {
private void generateCatchTargets(Consumer<? super CodeElement> consumer) {
// We attach all catch targets to bci zero, because trying to attach them
// to their range could subtly affect the order of exception processing
iterateExceptionHandlers(new ExceptionHandlerAction() {
@ -343,7 +345,7 @@ public final class CodeImpl
});
}
private void generateDebugElements(Consumer<CodeElement> consumer) {
private void generateDebugElements(Consumer<? super CodeElement> consumer) {
for (Attribute<?> a : attributes()) {
if (a.attributeMapper() == Attributes.characterRangeTable()) {
var attr = (BoundCharacterRangeTableAttribute) a;

View File

@ -101,14 +101,14 @@ public final class FieldImpl
builder.withField(fieldName(), fieldType(), new Consumer<>() {
@Override
public void accept(FieldBuilder fb) {
FieldImpl.this.forEachElement(fb);
FieldImpl.this.forEach(fb);
}
});
}
}
@Override
public void forEachElement(Consumer<FieldElement> consumer) {
public void forEach(Consumer<? super FieldElement> consumer) {
consumer.accept(flags());
for (Attribute<?> attr : attributes()) {
if (attr instanceof FieldElement e)

View File

@ -122,7 +122,7 @@ public final class MethodImpl
}
@Override
public void forEachElement(Consumer<MethodElement> consumer) {
public void forEach(Consumer<? super MethodElement> consumer) {
consumer.accept(flags());
for (Attribute<?> attr : attributes()) {
if (attr instanceof MethodElement e)
@ -140,7 +140,7 @@ public final class MethodImpl
new Consumer<>() {
@Override
public void accept(MethodBuilder mb) {
MethodImpl.this.forEachElement(mb);
MethodImpl.this.forEach(mb);
}
});
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -172,7 +172,7 @@ final class FingerPrint {
cm.thisClass().asInternalName(),
cm.superclass().map(ClassEntry::asInternalName).orElse(null),
cm.majorVersion());
cm.forEachElement(attrs);
cm.forEach(attrs);
return attrs;
}

View File

@ -222,7 +222,7 @@ final class EventInstrumentation {
// Only supports String, String[] and Boolean values
private static <T> T annotationValue(ClassModel classModel, ClassDesc classDesc, Class<T> type) {
String typeDescriptor = classDesc.descriptorString();
for (ClassElement ce : classModel.elements()) {
for (ClassElement ce : classModel) {
if (ce instanceof RuntimeVisibleAnnotationsAttribute rvaa) {
for (Annotation a : rvaa.annotations()) {
if (a.className().equalsString(typeDescriptor)) {
@ -260,7 +260,7 @@ final class EventInstrumentation {
Set<String> methodSet = new HashSet<>();
List<SettingDesc> settingDescs = new ArrayList<>();
for (MethodModel m : classModel.methods()) {
for (var me : m.elements()) {
for (var me : m) {
if (me instanceof RuntimeVisibleAnnotationsAttribute rvaa) {
for (Annotation a : rvaa.annotations()) {
// We can't really validate the method at this

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,7 +39,6 @@ import java.util.MissingResourceException;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.lang.classfile.ClassModel;
import java.lang.classfile.ClassFile;
import java.lang.classfile.CodeModel;
import java.lang.classfile.MethodModel;
@ -368,9 +367,9 @@ class JImageTask {
if (name.endsWith(".class") && !name.endsWith("module-info.class")) {
try {
byte[] bytes = reader.getResource(location);
ClassFile.of().parse(bytes).forEachElement(cle -> {
if (cle instanceof MethodModel mm) mm.forEachElement(me -> {
if (me instanceof CodeModel com) com.forEachElement(coe -> {
ClassFile.of().parse(bytes).forEach(cle -> {
if (cle instanceof MethodModel mm) mm.forEach(me -> {
if (me instanceof CodeModel com) com.forEach(coe -> {
//do nothing here, just visit each model element
});
});

View File

@ -133,7 +133,7 @@ public class Instrumentor {
}
}));
builder.withMethod(newName, mt, mm.flags().flagsMask(), mm::forEachElement);
builder.withMethod(newName, mt, mm.flags().flagsMask(), mm::forEach);
} else {
builder.accept(element);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -63,7 +63,7 @@ public class MHIllegalAccess {
*/
ClassTransform changeName = (cb, ce) -> {
if (ce instanceof MethodModel mm && mm.methodName().equalsString("m")) {
cb.withMethod("nemo", mm.methodTypeSymbol(), mm.flags().flagsMask(), mm::forEachElement);
cb.withMethod("nemo", mm.methodTypeSymbol(), mm.flags().flagsMask(), mm::forEach);
} else {
cb.accept(ce);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -100,7 +100,7 @@ public class LambdaAsm {
static void checkMethod(String cname, String mname, ConstantPool cp,
CodeAttribute code) throws IllegalArgumentException {
for (var inst : code.elements()) {
for (var inst : code) {
if (inst instanceof InvokeInstruction inv && (inv.opcode() == Opcode.INVOKESPECIAL
|| inv.opcode() == Opcode.INVOKEINTERFACE)) {
var ref = inv.method();

View File

@ -114,7 +114,7 @@ class AdaptCodeTest {
void testCopy() throws Exception {
var cc = ClassFile.of();
ClassModel cm = cc.parse(testClassPath);
byte[] newBytes = cc.build(cm.thisClass().asSymbol(), cb -> cm.forEachElement(cb));
byte[] newBytes = cc.build(cm.thisClass().asSymbol(), cm::forEach);
// TestUtil.writeClass(newBytes, "TestClass.class");
String result = (String)
new ByteArrayClassLoader(AdaptCodeTest.class.getClassLoader(), testClassName, newBytes)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -57,7 +57,7 @@ class BasicBlockTest {
try (InputStream in = BasicBlockTest.class.getResourceAsStream("BasicBlockTest.class")) {
var cc = ClassFile.of();
var classModel = cc.parse(in.readAllBytes());
cc.build(classModel.thisClass().asSymbol(), cb -> classModel.forEachElement(cb));
cc.build(classModel.thisClass().asSymbol(), classModel::forEach);
}
}
}

View File

@ -127,7 +127,7 @@ class ClassHierarchyInfoTest {
if (cle instanceof MethodModel mm) {
clb.transformMethod(mm, (mb, me) -> {
if (me instanceof CodeModel cm) {
mb.withCode(cob -> cm.forEachElement(cob));
mb.withCode(cm::forEach);
}
else
mb.with(me);

View File

@ -200,7 +200,7 @@ class CorpusTest {
byte[] newBytes = cc.build(
classModel.thisClass().asSymbol(),
classModel::forEachElement);
classModel::forEach);
var newModel = cc.parse(newBytes);
assertEqualsDeep(ClassRecord.ofClassModel(newModel, CompatibilityFilter.By_ClassBuilder),
ClassRecord.ofClassModel(classModel, CompatibilityFilter.By_ClassBuilder),

View File

@ -88,7 +88,7 @@ class LvtTest {
.orElseThrow();
List<LocalVariable> lvs = new ArrayList<>();
co.forEachElement(e -> {
co.forEach(e -> {
if (e instanceof LocalVariable l) lvs.add(l);
});
@ -198,7 +198,7 @@ class LvtTest {
.orElseThrow();
List<LocalVariableType> lvts = new ArrayList<>();
co.forEachElement(e -> {
co.forEach(e -> {
if (e instanceof LocalVariableType l) lvts.add(l);
});
@ -304,11 +304,11 @@ class LvtTest {
void skipDebugSkipsLVT() {
ClassModel c = ClassFile.of(ClassFile.DebugElementsOption.DROP_DEBUG).parse(fileBytes);
c.forEachElement(e -> {
c.forEach(e -> {
if (e instanceof MethodModel m) {
m.forEachElement(el -> {
m.forEach(el -> {
if (el instanceof CodeModel cm) {
cm.forEachElement(elem -> {
cm.forEach(elem -> {
assertFalse(elem instanceof LocalVariable);
assertFalse(elem instanceof LocalVariableType);
});

View File

@ -117,6 +117,6 @@ class OptionsTest {
if (e instanceof AttributedElement ae) ae.attributes().forEach(a ->
assertTrue(AttributeMapper.AttributeStability.UNSTABLE.ordinal() >= a.attributeMapper().stability().ordinal(),
() -> "class " + path + " contains unexpected " + a));
if (e instanceof CompoundElement ce) ce.forEachElement(ee -> testNoUnstable(path, (ClassFileElement)ee));
if (e instanceof CompoundElement ce) ce.forEach(ee -> testNoUnstable(path, (ClassFileElement)ee));
}
}

View File

@ -270,7 +270,7 @@ class StackMapsTest {
// classModel.superclass().ifPresent(cb::withSuperclass);
// cb.withInterfaces(classModel.interfaces());
// cb.withVersion(classModel.majorVersion(), classModel.minorVersion());
classModel.forEachElement(cb);
classModel.forEach(cb);
});
//then verify transformed bytecode

View File

@ -105,7 +105,7 @@ class TestRecordComponent {
void testOptions() throws Exception {
AtomicInteger count = new AtomicInteger(0);
ClassModel cm = ClassFile.of().parse(Files.readAllBytes(testClassPath));
cm.forEachElement((ce) -> {
cm.forEach((ce) -> {
if (ce instanceof RecordAttribute rm) {
count.addAndGet(rm.components().size());
}});

View File

@ -79,7 +79,7 @@ class VerifierSelfTest {
if (cle instanceof MethodModel mm) {
clb.transformMethod(mm, (mb, me) -> {
if (me instanceof CodeModel cm) {
mb.withCode(cob -> cm.forEachElement(cob));
mb.withCode(cob -> cm.forEach(cob));
}
else
mb.with(me);

View File

@ -75,7 +75,7 @@ class RebuildingTransformation {
cob2.transforming(new CodeRebuildingTransform(), cob3 ->
// first pass transforms bound to unbound instructions
cob3.transforming(new CodeRebuildingTransform(), cob4 -> {
com.forEachElement(cob4::with);
com.forEach(cob4::with);
com.findAttribute(Attributes.stackMapTable()).ifPresent(cob4::with);
}))));
case AnnotationDefaultAttribute a -> mb.with(AnnotationDefaultAttribute.of(transformAnnotationValue(a.defaultValue())));

View File

@ -218,7 +218,7 @@ public class Transforms {
if (me instanceof CodeModel xm) {
mb.withCode(xb -> {
xb.nop();
xm.forEachElement(new Consumer<>() {
xm.forEach(new Consumer<>() {
@Override
public void accept(CodeElement e) {
xb.with(e);
@ -270,7 +270,7 @@ public class Transforms {
ClassModel cm = cc.parse(bytes);
return cc.build(cm.thisClass().asSymbol(),
cb -> {
cm.forEachElement(cb);
cm.forEach(cb);
cb.withField("argleBargleWoogaWooga", ConstantDescs.CD_int, b -> { });
});
}),
@ -301,7 +301,7 @@ public class Transforms {
ClassModel cm = cc.parse(bytes);
return cc.build(cm.thisClass().asSymbol(),
cb -> {
cm.forEachElement(element -> {
cm.forEach(element -> {
if (element instanceof MethodModel mm
&& mm.methodName().stringValue().equals("hashCode")
&& mm.methodType().stringValue().equals("()Z")) {

View File

@ -390,7 +390,7 @@ class InlineCalls {
mm.methodTypeSymbol()
);
int offset = 0;
for (var ce : com.elements()) {
for (var ce : com) {
if (ce instanceof Instruction ins) {
if (ins instanceof InvokeInstruction inv) {
calls.add(new Call(caller, new MethodDesc(

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -101,11 +101,11 @@ public class ReadDeep extends AbstractCorpusBenchmark {
for (byte[] bytes : classes) {
int[] count = new int[1];
ClassModel cm = cc.parse(bytes);
cm.forEachElement(ce -> {
cm.forEach(ce -> {
if (ce instanceof MethodModel mm) {
mm.forEachElement(me -> {
mm.forEach(me -> {
if (me instanceof CodeModel xm) {
xm.forEachElement(xe -> {
xm.forEach(xe -> {
if (xe instanceof LoadInstruction) {
++count[0];
}

View File

@ -204,7 +204,7 @@ public class Transforms {
if (me instanceof CodeModel xm) {
mb.withCode(xb -> {
xb.nop();
xm.forEachElement(new Consumer<>() {
xm.forEach(new Consumer<>() {
@Override
public void accept(CodeElement e) {
xb.with(e);
@ -256,7 +256,7 @@ public class Transforms {
ClassModel cm = cc.parse(bytes);
return cc.build(cm.thisClass().asSymbol(),
cb -> {
cm.forEachElement(cb);
cm.forEach(cb);
cb.withField("argleBargleWoogaWooga", ConstantDescs.CD_int, b -> { });
});
}),
@ -287,7 +287,7 @@ public class Transforms {
ClassModel cm = cc.parse(bytes);
return cc.build(cm.thisClass().asSymbol(),
cb -> {
cm.forEachElement(element -> {
cm.forEach(element -> {
if (element instanceof MethodModel mm
&& mm.methodName().stringValue().equals("hashCode")
&& mm.methodType().stringValue().equals("()Z")) {