11package org .quiltmc .enigma .api ;
22
3+ import com .google .common .base .Predicates ;
4+ import com .google .common .collect .Streams ;
35import com .google .common .io .MoreFiles ;
4- import org .quiltmc .enigma .api .analysis .index .jar .JarIndex ;
6+ import org .objectweb .asm .tree .ClassNode ;
7+ import org .quiltmc .enigma .api .analysis .index .jar .CombinedJarIndex ;
8+ import org .quiltmc .enigma .api .analysis .index .jar .EntryIndex ;
9+ import org .quiltmc .enigma .api .analysis .index .jar .InheritanceIndex ;
510import org .quiltmc .enigma .api .analysis .index .jar .LibrariesJarIndex ;
611import org .quiltmc .enigma .api .analysis .index .jar .MainJarIndex ;
12+ import org .quiltmc .enigma .api .analysis .index .jar .ReferenceIndex ;
713import org .quiltmc .enigma .api .analysis .index .mapping .MappingsIndex ;
14+ import org .quiltmc .enigma .api .class_provider .ClasspathClassProvider ;
815import org .quiltmc .enigma .api .class_provider .ProjectClassProvider ;
916import org .quiltmc .enigma .api .translation .mapping .serde .MappingParseException ;
17+ import org .quiltmc .enigma .api .translation .representation .entry .ClassEntry ;
18+ import org .quiltmc .enigma .api .translation .representation .entry .FieldEntry ;
19+ import org .quiltmc .enigma .api .translation .representation .entry .MethodEntry ;
1020import org .quiltmc .enigma .impl .analysis .ClassLoaderClassProvider ;
1121import org .quiltmc .enigma .api .service .EnigmaService ;
1222import org .quiltmc .enigma .api .service .EnigmaServiceContext ;
2535import org .quiltmc .enigma .api .translation .mapping .tree .EntryTree ;
2636import org .quiltmc .enigma .api .translation .mapping .tree .HashEntryTree ;
2737import org .quiltmc .enigma .api .translation .representation .entry .Entry ;
38+ import org .quiltmc .enigma .impl .analysis .index .AbstractJarIndex ;
39+ import org .quiltmc .enigma .impl .analysis .index .IndexClassVisitor ;
2840import org .quiltmc .enigma .util .Either ;
2941import org .quiltmc .enigma .util .I18n ;
3042import org .quiltmc .enigma .util .Utils ;
4355import java .nio .file .attribute .BasicFileAttributes ;
4456import java .sql .DriverManager ;
4557import java .util .ArrayList ;
58+ import java .util .Collection ;
4659import java .util .Collections ;
4760import java .util .HashSet ;
4861import java .util .List ;
4962import java .util .Map ;
63+ import java .util .Objects ;
5064import java .util .Optional ;
5165import java .util .Properties ;
5266import java .util .ServiceLoader ;
5367import java .util .Set ;
5468import java .util .concurrent .atomic .AtomicReference ;
69+ import java .util .function .Predicate ;
70+ import java .util .stream .Collectors ;
71+ import java .util .stream .Stream ;
5572
5673public class Enigma {
5774 public static final String NAME = "Enigma" ;
@@ -80,19 +97,27 @@ public static Builder builder() {
8097
8198 public EnigmaProject openJar (Path path , ClassProvider libraryClassProvider , ProgressListener progress ) throws IOException {
8299 JarClassProvider jarClassProvider = new JarClassProvider (path );
83- JarIndex index = MainJarIndex .empty ();
84- JarIndex libIndex = LibrariesJarIndex .empty ();
100+ AbstractJarIndex jarIndex = MainJarIndex .empty ();
101+ AbstractJarIndex libIndex = LibrariesJarIndex .empty ();
102+ AbstractJarIndex comboIndex = CombinedJarIndex .empty ();
85103
86104 ClassLoaderClassProvider jreProvider = new ClassLoaderClassProvider (DriverManager .class .getClassLoader ());
87- CombiningClassProvider librariesProvider = new CombiningClassProvider (jreProvider , libraryClassProvider );
88- ClassProvider mainProjectProvider = new ObfuscationFixClassProvider (new CachingClassProvider (jarClassProvider ), index );
105+ ClasspathClassProvider javaClassProvider = new ClasspathClassProvider ();
106+ CombiningClassProvider librariesProvider = new CombiningClassProvider (jreProvider , javaClassProvider , libraryClassProvider );
107+ ClassProvider mainProjectProvider = new ObfuscationFixClassProvider (new CachingClassProvider (jarClassProvider ), jarIndex );
89108 ProjectClassProvider projectClassProvider = new ProjectClassProvider (mainProjectProvider , librariesProvider );
90109
91110 // main index
92- this .index (index , projectClassProvider , progress );
111+ this .index (jarIndex , projectClassProvider , progress , "jar" , false , null );
112+
113+ // TODO make filtering toggleable with arg once JavaClassProvider is used
114+ final Predicate <String > mainReferencedPredicate = this .createMainReferencedPredicate (jarIndex , projectClassProvider );
93115
94116 // lib index
95- this .index (libIndex , projectClassProvider , progress );
117+ this .index (libIndex , projectClassProvider , progress , "jar" , true , mainReferencedPredicate );
118+
119+ // combined main and lib index
120+ this .index (comboIndex , projectClassProvider , progress , "combined" , true , mainReferencedPredicate );
96121
97122 // name proposal
98123 var nameProposalServices = this .getNameProposalServices ();
@@ -103,7 +128,7 @@ public EnigmaProject openJar(Path path, ClassProvider libraryClassProvider, Prog
103128 int j = 1 ;
104129 for (var service : nameProposalServices ) {
105130 progress .step (j ++, I18n .translateFormatted ("progress.jar.name_proposal.proposer" , service .getId ()));
106- Map <Entry <?>, EntryMapping > proposed = service .getProposedNames (this , index );
131+ Map <Entry <?>, EntryMapping > proposed = service .getProposedNames (this , jarIndex );
107132
108133 if (proposed != null ) {
109134 for (var entry : proposed .entrySet ()) {
@@ -118,23 +143,89 @@ public EnigmaProject openJar(Path path, ClassProvider libraryClassProvider, Prog
118143 MappingsIndex mappingsIndex = MappingsIndex .empty ();
119144 mappingsIndex .indexMappings (proposedNames , progress );
120145
121- return new EnigmaProject (this , path , mainProjectProvider , index , libIndex , mappingsIndex , proposedNames , Utils .zipSha1 (path ));
146+ return new EnigmaProject (this , path , mainProjectProvider , jarIndex , libIndex , comboIndex , mappingsIndex , proposedNames , Utils .zipSha1 (path ));
122147 }
123148
124- private void index (JarIndex index , ProjectClassProvider classProvider , ProgressListener progress ) {
125- boolean libraries = index instanceof LibrariesJarIndex ;
126- String progressKey = libraries ? "libs" : "jar" ;
127- index .indexJar (classProvider , progress );
149+ private Predicate <String > createMainReferencedPredicate (AbstractJarIndex mainIndex , ProjectClassProvider classProvider ) {
150+ final EntryIndex mainEntryIndex = mainIndex .getIndex (EntryIndex .class );
151+
152+ final EntryIndex entryIndex = new EntryIndex ();
153+ final ReferenceIndex referenceIndex = new ReferenceIndex ();
154+ final InheritanceIndex inheritanceIndex = new InheritanceIndex (entryIndex );
155+
156+ final Collection <String > allClassNames = classProvider .getClassNames ();
157+ for (final String className : allClassNames ) {
158+ final ClassNode classNode = Objects .requireNonNull (classProvider .get (className ));
159+ classNode .accept (new IndexClassVisitor (entryIndex , Enigma .ASM_VERSION ));
160+ classNode .accept (new IndexClassVisitor (referenceIndex , Enigma .ASM_VERSION ));
161+ classNode .accept (new IndexClassVisitor (inheritanceIndex , Enigma .ASM_VERSION ));
162+ }
163+
164+ return className -> {
165+ final ClassEntry classEntry = new ClassEntry (className );
166+ if (mainEntryIndex .hasClass (classEntry )) {
167+ return true ;
168+ }
169+
170+ if (inheritanceIndex .getChildren (classEntry ).stream ().anyMatch (mainEntryIndex ::hasClass )) {
171+ return true ;
172+ }
173+
174+ final boolean typeReferenced = Streams
175+ .concat (
176+ referenceIndex .getReferencesToClass (classEntry ).stream (),
177+ referenceIndex .getMethodTypeReferencesToClass (classEntry ).stream (),
178+ referenceIndex .getFieldTypeReferencesToClass (classEntry ).stream ()
179+ )
180+ .anyMatch (reference ->
181+ mainEntryIndex .hasClass (reference .entry ) || mainEntryIndex .hasEntry (reference .context )
182+ );
183+
184+ if (typeReferenced ) {
185+ return true ;
186+ }
187+
188+ final List <MethodEntry > mainMethods = mainIndex .getChildrenByClass ().values ().stream ()
189+ .flatMap (entry -> entry instanceof MethodEntry method ? Stream .of (method ) : Stream .empty ())
190+ .toList ();
191+
192+ final boolean methodReferenced = mainMethods .stream ()
193+ .flatMap (method -> referenceIndex .getMethodsReferencedBy (method ).stream ())
194+ .map (MethodEntry ::getParent )
195+ .anyMatch (classEntry ::equals );
196+ if (methodReferenced ) {
197+ return true ;
198+ }
199+
200+ // field referenced
201+ return mainMethods .stream ()
202+ .flatMap (method -> referenceIndex .getFieldsReferencedBy (method ).stream ())
203+ .map (FieldEntry ::getParent )
204+ .anyMatch (classEntry ::equals );
205+ };
206+ }
207+
208+ private void index (
209+ AbstractJarIndex index , ProjectClassProvider classProvider , ProgressListener progress , String progressKey ,
210+ boolean includesLibraries , @ Nullable Predicate <String > classNameFilter
211+ ) {
212+ if (classNameFilter == null ) {
213+ index .indexJar (classProvider , progress );
214+ classNameFilter = Predicates .alwaysTrue ();
215+ } else {
216+ index .indexJar (classProvider , progress , classNameFilter );
217+ }
128218
129219 List <JarIndexerService > indexers = this .services .get (JarIndexerService .TYPE );
130220 progress .init (indexers .size (), I18n .translate ("progress." + progressKey + ".custom_indexing" ));
131221
132222 int i = 1 ;
133223 for (var service : indexers ) {
134- if (!(libraries && !service .shouldIndexLibraries ())) {
224+ if (!(includesLibraries && !service .shouldIndexLibraries ())) {
135225 progress .step (i ++, I18n .translateFormatted ("progress." + progressKey + ".custom_indexing.indexer" , service .getId ()));
136- var names = libraries ? classProvider .getLibraryClassNames () : classProvider .getMainClassNames ();
137- Set <String > scope = new HashSet <>(names );
226+ Set <String > scope = index .getIndexableClassNames (classProvider ).stream ()
227+ .filter (classNameFilter )
228+ .collect (Collectors .toCollection (HashSet ::new ));
138229 service .acceptJar (scope , classProvider , index );
139230 }
140231 }
0 commit comments