3939import org .quiltmc .enigma_plugin .index .simple_type_single .SimpleTypeFieldNamesRegistry .Name ;
4040import org .quiltmc .enigma_plugin .util .AsmUtil ;
4141import org .quiltmc .enigma_plugin .util .Descriptors ;
42+ import org .tinylog .Logger ;
4243
4344import java .nio .file .Path ;
4445import java .util .ArrayList ;
46+ import java .util .Arrays ;
4547import java .util .HashMap ;
4648import java .util .HashSet ;
4749import java .util .List ;
4850import java .util .Map ;
4951import java .util .Set ;
52+ import java .util .stream .Collectors ;
5053
5154/**
5255 * Index of fields/local variables that are of a rather simple type (as-in easy to guess the variable name) and which
@@ -57,9 +60,11 @@ public class SimpleTypeSingleIndex extends Index {
5760 private final Map <LocalVariableEntry , List <String >> parameterFallbacks = new HashMap <>();
5861 private final Map <FieldEntry , String > fields = new HashMap <>();
5962 private final Map <ClassNode , Map <String , FieldBuildingEntry >> fieldCache = new HashMap <>();
60- private SimpleTypeFieldNamesRegistry registry ;
63+ private final Set < String > unverifiedTypes = new HashSet <>() ;
6164
65+ private SimpleTypeFieldNamesRegistry registry ;
6266 private InheritanceIndex inheritance ;
67+ private VerificationLevel verificationLevel = VerificationLevel .DEFAULT ;
6368
6469 public SimpleTypeSingleIndex () {
6570 super (null );
@@ -69,6 +74,26 @@ public SimpleTypeSingleIndex() {
6974 public void withContext (EnigmaServiceContext <JarIndexerService > context ) {
7075 super .withContext (context );
7176
77+ this .verificationLevel = context .getSingleArgument (Arguments .SIMPLE_TYPE_VERIFICATION_ERROR_LEVEL )
78+ .map (value -> {
79+ try {
80+ return VerificationLevel .valueOf (value );
81+ } catch (IllegalArgumentException e ) {
82+ throw new IllegalStateException (
83+ "Invalid %s value: \" %s\" ; must be one of %s" .formatted (
84+ Arguments .SIMPLE_TYPE_VERIFICATION_ERROR_LEVEL ,
85+ value ,
86+ Arrays .stream (VerificationLevel .values ())
87+ .map (Enum ::name )
88+ .map (name -> '"' + name + '"' )
89+ .collect (Collectors .joining (", " ))
90+ ),
91+ e
92+ );
93+ }
94+ })
95+ .orElse (VerificationLevel .DEFAULT );
96+
7297 this .loadRegistry (context .getSingleArgument (Arguments .SIMPLE_TYPE_FIELD_NAMES_PATH )
7398 .map (context ::getPath ).orElse (null ));
7499 }
@@ -86,6 +111,11 @@ public void loadRegistry(Path path) {
86111
87112 this .registry = new SimpleTypeFieldNamesRegistry (path );
88113 this .registry .read ();
114+
115+ this .unverifiedTypes .clear ();
116+ if (this .verificationLevel != VerificationLevel .NONE ) {
117+ this .registry .streamTypes ().forEach (this .unverifiedTypes ::add );
118+ }
89119 }
90120
91121 @ Override
@@ -117,6 +147,29 @@ public Set<LocalVariableEntry> getParams() {
117147 return this .parameters .keySet ();
118148 }
119149
150+ public void verifyTypes () {
151+ if (this .verificationLevel != VerificationLevel .NONE ) {
152+ if (!this .unverifiedTypes .isEmpty ()) {
153+ boolean single = this .unverifiedTypes .size () == 1 ;
154+ StringBuilder message = new StringBuilder ("The following simple type field name type" );
155+ message .append (single ? " is" : "s are" );
156+ message .append (" missing:" );
157+
158+ if (single ) {
159+ message .append (' ' ).append (this .unverifiedTypes .iterator ().next ());
160+ } else {
161+ this .unverifiedTypes .forEach (type -> message .append ("\n \t " ).append (type ));
162+ }
163+
164+ if (this .verificationLevel == VerificationLevel .WARN ) {
165+ Logger .warn (message );
166+ } else {
167+ throw new IllegalStateException (message .toString ());
168+ }
169+ }
170+ }
171+ }
172+
120173 @ TestOnly
121174 public List <LocalVariableEntry > getParamsOf (MethodEntry methodEntry ) {
122175 var params = new ArrayList <LocalVariableEntry >();
@@ -141,6 +194,8 @@ public void visitClassNode(ClassProvider provider, ClassNode node) {
141194
142195 var parentEntry = new ClassEntry (node .name );
143196
197+ this .unverifiedTypes .remove (node .name );
198+
144199 this .collectMatchingFields (provider , node ).forEach ((name , entry ) -> {
145200 if (!entry .isNull ()) {
146201 var fieldEntry = new FieldEntry (parentEntry , entry .node ().name , new TypeDescriptor (entry .node ().desc ));
@@ -207,8 +262,8 @@ private Map<String, FieldBuildingEntry> collectMatchingFields(ClassProvider clas
207262 }
208263 }
209264
210- if (field .desc . charAt ( 0 ) != 'L' ) continue ;
211- String type = field . desc . substring ( 1 , field . desc . length () - 1 ) ;
265+ String type = this . verifyTypeOrNull (field .desc ) ;
266+ if ( type == null ) continue ;
212267
213268 var entry = this .getEntry (type );
214269 if (entry != null ) {
@@ -268,9 +323,8 @@ private Map<String, ParameterBuildingEntry> collectMatchingParameters(MethodNode
268323 if (bannedTypes .contains (parameters .get (index ).type ())) continue ;
269324
270325 ParameterNode node = method .parameters .get (index );
271- String desc = parameters .get (index ).getDescriptor ();
272- if (desc .charAt (0 ) != 'L' ) continue ;
273- String type = desc .substring (1 , desc .length () - 1 );
326+ String type = this .verifyTypeOrNull (parameters .get (index ).getDescriptor ());
327+ if (type == null ) continue ;
274328
275329 var entry = this .getEntry (type );
276330 if (entry != null ) {
@@ -334,6 +388,19 @@ private SimpleTypeFieldNamesRegistry.Entry getEntry(String type) {
334388 return null ;
335389 }
336390
391+ @ Nullable
392+ private String verifyTypeOrNull (String descriptor ) {
393+ if (descriptor .charAt (0 ) != 'L' ) {
394+ return null ;
395+ }
396+
397+ String type = descriptor .substring (1 , descriptor .length () - 1 );
398+
399+ this .unverifiedTypes .remove (type );
400+
401+ return type ;
402+ }
403+
337404 private record FieldBuildingEntry (FieldNode node , Name name , SimpleTypeFieldNamesRegistry .Entry entry ) {
338405 public static FieldBuildingEntry createNull (SimpleTypeFieldNamesRegistry .Entry entry ) {
339406 return new FieldBuildingEntry (null , null , entry );
@@ -353,4 +420,10 @@ public boolean isNull() {
353420 return this .node == null ;
354421 }
355422 }
423+
424+ private enum VerificationLevel {
425+ NONE , WARN , THROW ;
426+
427+ static final VerificationLevel DEFAULT = WARN ;
428+ }
356429}
0 commit comments