Skip to content

Commit f6651e4

Browse files
committed
Refactor MappingApplier to not be workspace-scoped, and usable for any arbitrary workspace
1 parent 5484258 commit f6651e4

File tree

9 files changed

+166
-74
lines changed

9 files changed

+166
-74
lines changed

recaf-core/src/main/java/software/coley/recaf/services/mapping/MappingApplier.java

+31-37
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package software.coley.recaf.services.mapping;
22

33
import jakarta.annotation.Nonnull;
4-
import jakarta.inject.Inject;
4+
import jakarta.annotation.Nullable;
55
import org.objectweb.asm.ClassReader;
66
import org.objectweb.asm.ClassVisitor;
77
import org.objectweb.asm.ClassWriter;
8-
import software.coley.recaf.cdi.WorkspaceScoped;
98
import software.coley.recaf.info.JvmClassInfo;
109
import software.coley.recaf.info.properties.builtin.HasMappedReferenceProperty;
1110
import software.coley.recaf.info.properties.builtin.OriginalClassNameProperty;
1211
import software.coley.recaf.info.properties.builtin.RemapOriginTaskProperty;
13-
import software.coley.recaf.services.Service;
1412
import software.coley.recaf.services.inheritance.InheritanceGraph;
15-
import software.coley.recaf.services.inheritance.InheritanceGraphService;
1613
import software.coley.recaf.services.mapping.aggregate.AggregateMappingManager;
14+
import software.coley.recaf.services.workspace.WorkspaceManager;
1715
import software.coley.recaf.util.threading.ThreadPoolFactory;
1816
import software.coley.recaf.util.threading.ThreadUtil;
1917
import software.coley.recaf.util.visitors.IllegalSignatureRemovingVisitor;
@@ -22,7 +20,6 @@
2220
import software.coley.recaf.workspace.model.resource.WorkspaceResource;
2321

2422
import java.util.Collection;
25-
import java.util.Objects;
2623
import java.util.concurrent.ExecutorService;
2724
import java.util.stream.Stream;
2825

@@ -33,27 +30,33 @@
3330
* @author Matt Coley
3431
* @see MappingResults
3532
*/
36-
@WorkspaceScoped
37-
public class MappingApplier implements Service {
38-
public static final String SERVICE_ID = "mapping-applier";
39-
private static final ExecutorService applierThreadPool = ThreadPoolFactory.newFixedThreadPool(SERVICE_ID);
33+
public class MappingApplier {
34+
private static final ExecutorService applierThreadPool = ThreadPoolFactory.newFixedThreadPool(MappingApplierService.SERVICE_ID);
4035
private final InheritanceGraph inheritanceGraph;
4136
private final AggregateMappingManager aggregateMappingManager;
4237
private final MappingListeners listeners;
4338
private final Workspace workspace;
44-
private final MappingApplierConfig config;
45-
46-
@Inject
47-
public MappingApplier(@Nonnull MappingApplierConfig config,
48-
@Nonnull InheritanceGraphService graphService,
49-
@Nonnull AggregateMappingManager aggregateMappingManager,
50-
@Nonnull MappingListeners listeners,
51-
@Nonnull Workspace workspace) {
52-
this.inheritanceGraph = Objects.requireNonNull(graphService.getCurrentWorkspaceInheritanceGraph(), "Graph not created");
39+
40+
/**
41+
* @param workspace
42+
* Workspace to apply mappings in.
43+
* @param inheritanceGraph
44+
* Inheritance graph for the given workspace.
45+
* @param listeners
46+
* Application mapping listeners
47+
* <i>(If the target workspace is the {@link WorkspaceManager#getCurrent() current one})</i>
48+
* @param aggregateMappingManager
49+
* Aggregate mappings for tracking applications in the current workspace
50+
* <i>(If the target workspace is the {@link WorkspaceManager#getCurrent() current one})</i>
51+
*/
52+
public MappingApplier(@Nonnull Workspace workspace,
53+
@Nonnull InheritanceGraph inheritanceGraph,
54+
@Nullable MappingListeners listeners,
55+
@Nullable AggregateMappingManager aggregateMappingManager) {
56+
this.inheritanceGraph = inheritanceGraph;
5357
this.aggregateMappingManager = aggregateMappingManager;
5458
this.listeners = listeners;
5559
this.workspace = workspace;
56-
this.config = config;
5760
}
5861

5962
/**
@@ -76,8 +79,10 @@ public MappingResults applyToClasses(@Nonnull Mappings mappings,
7679
@Nonnull JvmClassBundle bundle,
7780
@Nonnull Collection<JvmClassInfo> classes) {
7881
mappings = enrich(mappings);
79-
MappingResults results = new MappingResults(mappings, listeners.createBundledMappingApplicationListener())
80-
.withAggregateManager(aggregateMappingManager);
82+
MappingApplicationListener listener = listeners == null ? null : listeners.createBundledMappingApplicationListener();
83+
MappingResults results = new MappingResults(mappings, listener);
84+
if (aggregateMappingManager != null)
85+
results.withAggregateManager(aggregateMappingManager);
8186

8287
// Apply mappings to the provided classes, collecting into the results model.
8388
Mappings finalMappings = mappings;
@@ -101,14 +106,15 @@ public MappingResults applyToClasses(@Nonnull Mappings mappings,
101106
@Nonnull
102107
public MappingResults applyToPrimaryResource(@Nonnull Mappings mappings) {
103108
mappings = enrich(mappings);
104-
WorkspaceResource resource = workspace.getPrimaryResource();
105-
106-
MappingResults results = new MappingResults(mappings, listeners.createBundledMappingApplicationListener())
107-
.withAggregateManager(aggregateMappingManager);
109+
MappingApplicationListener listener = listeners == null ? null : listeners.createBundledMappingApplicationListener();
110+
MappingResults results = new MappingResults(mappings, listener);
111+
if (aggregateMappingManager != null)
112+
results.withAggregateManager(aggregateMappingManager);
108113

109114
// Apply mappings to all classes in the primary resource, collecting into the results model.
110115
Mappings finalMappings = mappings;
111116
ExecutorService service = ThreadUtil.phasingService(applierThreadPool);
117+
WorkspaceResource resource = workspace.getPrimaryResource();
112118
Stream.concat(resource.jvmClassBundleStream(), resource.versionedJvmClassBundleStream()).forEach(bundle -> {
113119
bundle.forEach(classInfo -> {
114120
service.execute(() -> dumpIntoResults(results, workspace, resource, bundle, classInfo, finalMappings));
@@ -199,16 +205,4 @@ private static void dumpIntoResults(@Nonnull MappingResults results,
199205
results.add(workspace, resource, bundle, classInfo, updatedInfo);
200206
}
201207
}
202-
203-
@Nonnull
204-
@Override
205-
public String getServiceId() {
206-
return SERVICE_ID;
207-
}
208-
209-
@Nonnull
210-
@Override
211-
public MappingApplierConfig getServiceConfig() {
212-
return config;
213-
}
214208
}

recaf-core/src/main/java/software/coley/recaf/services/mapping/MappingApplierConfig.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import software.coley.recaf.services.ServiceConfig;
88

99
/**
10-
* Config for {@link MappingApplier}
10+
* Config for {@link MappingApplierService}
1111
*
1212
* @author Matt Coley
1313
*/
1414
@ApplicationScoped
1515
public class MappingApplierConfig extends BasicConfigContainer implements ServiceConfig {
1616
@Inject
1717
public MappingApplierConfig() {
18-
super(ConfigGroups.SERVICE_MAPPING, MappingApplier.SERVICE_ID + CONFIG_SUFFIX);
18+
super(ConfigGroups.SERVICE_MAPPING, MappingApplierService.SERVICE_ID + CONFIG_SUFFIX);
1919
}
2020
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package software.coley.recaf.services.mapping;
2+
3+
import jakarta.annotation.Nonnull;
4+
import jakarta.annotation.Nullable;
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
import jakarta.inject.Inject;
7+
import software.coley.recaf.services.Service;
8+
import software.coley.recaf.services.inheritance.InheritanceGraph;
9+
import software.coley.recaf.services.inheritance.InheritanceGraphService;
10+
import software.coley.recaf.services.mapping.aggregate.AggregateMappingManager;
11+
import software.coley.recaf.services.workspace.WorkspaceManager;
12+
import software.coley.recaf.util.threading.ThreadPoolFactory;
13+
import software.coley.recaf.workspace.model.Workspace;
14+
15+
import java.util.Objects;
16+
import java.util.concurrent.ExecutorService;
17+
18+
/**
19+
* Service offering the creation of {@link MappingApplier mapping appliers} for workspaces.
20+
*
21+
* @author Matt Coley
22+
* @see MappingApplier
23+
*/
24+
@ApplicationScoped
25+
public class MappingApplierService implements Service {
26+
public static final String SERVICE_ID = "mapping-applier";
27+
private static final ExecutorService applierThreadPool = ThreadPoolFactory.newFixedThreadPool(SERVICE_ID);
28+
private final InheritanceGraphService inheritanceGraphService;
29+
private final AggregateMappingManager aggregateMappingManager;
30+
private final MappingListeners listeners;
31+
private final WorkspaceManager workspaceManager;
32+
private final MappingApplierConfig config;
33+
34+
@Inject
35+
public MappingApplierService(@Nonnull MappingApplierConfig config,
36+
@Nonnull InheritanceGraphService inheritanceGraphService,
37+
@Nonnull AggregateMappingManager aggregateMappingManager,
38+
@Nonnull MappingListeners listeners,
39+
@Nonnull WorkspaceManager workspaceManager) {
40+
this.inheritanceGraphService = inheritanceGraphService;
41+
this.aggregateMappingManager = aggregateMappingManager;
42+
this.listeners = listeners;
43+
this.workspaceManager = workspaceManager;
44+
this.config = config;
45+
}
46+
47+
/**
48+
* @param workspace
49+
* Workspace to apply mappings in.
50+
*
51+
* @return Applier for the given workspace.
52+
*/
53+
@Nonnull
54+
public MappingApplier inWorkspace(@Nonnull Workspace workspace) {
55+
if (workspace == workspaceManager.getCurrent())
56+
return Objects.requireNonNull(inCurrentWorkspace(), "Failed to access current workspace for mapping application");
57+
return new MappingApplier(workspace, inheritanceGraphService.newInheritanceGraph(workspace), null, null);
58+
}
59+
60+
/**
61+
* @return Applier for the current workspace, or {@code null} if no workspace is open.
62+
*/
63+
@Nullable
64+
public MappingApplier inCurrentWorkspace() {
65+
Workspace workspace = workspaceManager.getCurrent();
66+
if (workspace == null)
67+
return null;
68+
InheritanceGraph currentWorkspaceInheritanceGraph = inheritanceGraphService.getCurrentWorkspaceInheritanceGraph();
69+
if (currentWorkspaceInheritanceGraph == null)
70+
return null;
71+
return new MappingApplier(workspace, currentWorkspaceInheritanceGraph, listeners, aggregateMappingManager);
72+
}
73+
74+
@Nonnull
75+
@Override
76+
public String getServiceId() {
77+
return SERVICE_ID;
78+
}
79+
80+
@Nonnull
81+
@Override
82+
public MappingApplierConfig getServiceConfig() {
83+
return config;
84+
}
85+
}

recaf-core/src/test/java/software/coley/recaf/services/comment/CommentManagerTest.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package software.coley.recaf.services.comment;
22

3-
import org.junit.jupiter.api.*;
3+
import org.junit.jupiter.api.BeforeAll;
4+
import org.junit.jupiter.api.MethodOrderer;
5+
import org.junit.jupiter.api.Order;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.TestMethodOrder;
48
import software.coley.recaf.info.JvmClassInfo;
59
import software.coley.recaf.path.ClassPathNode;
610
import software.coley.recaf.services.decompile.DecompileResult;
711
import software.coley.recaf.services.decompile.DecompilerManager;
812
import software.coley.recaf.services.mapping.IntermediateMappings;
9-
import software.coley.recaf.services.mapping.MappingApplier;
13+
import software.coley.recaf.services.mapping.MappingApplierService;
1014
import software.coley.recaf.services.mapping.MappingResults;
1115
import software.coley.recaf.services.workspace.WorkspaceManager;
1216
import software.coley.recaf.test.TestBase;
@@ -26,7 +30,7 @@ class CommentManagerTest extends TestBase {
2630
static CommentManager commentManager;
2731
static CommentManagerConfig commentManagerConfig;
2832
static DecompilerManager decompilerManager;
29-
static MappingApplier mappingApplier;
33+
static MappingApplierService mappingApplierService;
3034
static JvmClassInfo classToDecompile;
3135
static Workspace workspace;
3236

@@ -41,7 +45,7 @@ static void setup() throws IOException {
4145
commentManager = recaf.get(CommentManager.class);
4246
commentManagerConfig = recaf.get(CommentManagerConfig.class);
4347
decompilerManager = recaf.get(DecompilerManager.class);
44-
mappingApplier = recaf.get(MappingApplier.class);
48+
mappingApplierService = recaf.get(MappingApplierService.class);
4549
}
4650

4751
@Test
@@ -97,7 +101,7 @@ void testCommentsGetMigratedAfterRemapping() {
97101
mappings.addMethod(classToDecompile.getName(), "()V", "methodWithLocalVariables", "fizz");
98102

99103
// Apply the mappings
100-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
104+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
101105
ClassPathNode postMappingPath = results.getPostMappingPath(classToDecompile.getName());
102106
assertNotNull(postMappingPath, "Post-mapping path does not exist in mapping results");
103107
results.apply();

recaf-core/src/test/java/software/coley/recaf/services/inheritance/InheritanceAndRenamingTest.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import software.coley.recaf.info.builder.JvmClassInfoBuilder;
88
import software.coley.recaf.services.mapping.IntermediateMappings;
99
import software.coley.recaf.services.mapping.MappingApplier;
10+
import software.coley.recaf.services.mapping.MappingApplierService;
1011
import software.coley.recaf.services.mapping.MappingResults;
1112
import software.coley.recaf.test.TestBase;
1213
import software.coley.recaf.test.TestClassUtils;
@@ -26,7 +27,7 @@
2627
class InheritanceAndRenamingTest extends TestBase {
2728
static Workspace workspace;
2829
static InheritanceGraph inheritanceGraph;
29-
static MappingApplier mappingApplier;
30+
static MappingApplierService mappingApplierService;
3031
static JvmClassInfo[] generatedClasses;
3132

3233
@BeforeAll
@@ -48,7 +49,7 @@ static void setup() {
4849
inheritanceGraph.toString(); // Force immediate init.
4950

5051
// Get mapping applier
51-
mappingApplier = recaf.get(MappingApplier.class);
52+
mappingApplierService = recaf.get(MappingApplierService.class);
5253
}
5354

5455
@Test
@@ -64,7 +65,7 @@ void test() {
6465
IntermediateMappings mappings = new IntermediateMappings();
6566
for (int i = 1; i <= 5; i++)
6667
mappings.addClass("I" + i, "R" + i);
67-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
68+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
6869
results.apply();
6970

7071
// Very old classes are removed from the graph

recaf-core/src/test/java/software/coley/recaf/services/mapping/MappingApplierTest.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class MappingApplierTest extends TestBase {
4343
WorkspaceResource resource;
4444
AggregateMappingManager aggregateMappingManager;
4545
InheritanceGraph inheritanceGraph;
46-
MappingApplier mappingApplier;
46+
MappingApplierService mappingApplierService;
4747

4848
@BeforeAll
4949
static void setupGenerator() {
@@ -74,7 +74,7 @@ void prepareWorkspace() throws IOException {
7474
aggregateMappingManager = recaf.get(AggregateMappingManager.class);
7575
inheritanceGraph = recaf.get(InheritanceGraphService.class).getCurrentWorkspaceInheritanceGraph();
7676
mappingGenerator = recaf.get(MappingGenerator.class);
77-
mappingApplier = recaf.get(MappingApplier.class);
77+
mappingApplierService = recaf.get(MappingApplierService.class);
7878
}
7979

8080
@Test
@@ -105,7 +105,7 @@ public boolean shouldMapMethod(@Nonnull ClassInfo owner, @Nonnull MethodMember m
105105
});
106106

107107
// Preview the mapping operation
108-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
108+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
109109

110110
// The supplier class we define should be remapped.
111111
// The runner class (AnonymousLambda) itself should not be remapped, but should be updated to point to
@@ -160,7 +160,7 @@ public boolean shouldMapMethod(@Nonnull ClassInfo owner, @Nonnull MethodMember m
160160
});
161161

162162
// Preview the mapping operation
163-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
163+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
164164

165165
// The enum class we define should be remapped.
166166
// The runner class (DummyEnumPrinter) itself should not be remapped, but should be updated to point to
@@ -199,7 +199,7 @@ public boolean shouldMapClass(@Nonnull ClassInfo info) {
199199
});
200200

201201
// Preview the mapping operation
202-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
202+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
203203

204204
// The annotation class we define should be remapped.
205205
// The user class (ClassWithAnnotation) itself should not be remapped,
@@ -254,7 +254,7 @@ public boolean shouldMapMethod(@Nonnull ClassInfo owner, @Nonnull MethodMember m
254254
});
255255

256256
// Preview the mapping operation
257-
MappingResults results = mappingApplier.applyToPrimaryResource(mappings);
257+
MappingResults results = mappingApplierService.inCurrentWorkspace().applyToPrimaryResource(mappings);
258258

259259
assertNotNull(mappings.getMappedClassName(overlapInterfaceAName), "OverlapInterfaceA should be remapped");
260260
assertNotNull(mappings.getMappedClassName(overlapInterfaceBName), "OverlapInterfaceB should be remapped");

0 commit comments

Comments
 (0)