Skip to content

Commit

Permalink
Merge pull request #11 from OroArmorModding/inherit-simple-type-names
Browse files Browse the repository at this point in the history
Add a way for simple type names to allow inheritance for subclasses
  • Loading branch information
OroArmor authored Aug 23, 2024
2 parents e9352b3 + 5e571a5 commit 80f1c3e
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public void read() {
String localName = null;
String staticName = null;
boolean exclusive = false;
boolean inherit = false;
List<Name> fallback = Collections.emptyList();

reader.beginObject();
Expand All @@ -81,6 +82,7 @@ public void read() {
case "local_name" -> localName = reader.nextString();
case "static_name" -> staticName = reader.nextString();
case "exclusive" -> exclusive = reader.nextBoolean();
case "inherit" -> inherit = reader.nextBoolean();
case "fallback" -> {
reader.beginArray();

Expand All @@ -101,7 +103,7 @@ public void read() {

if (staticName == null) staticName = CasingUtil.toScreamingSnakeCase(localName);

this.entries.put(type, new Entry(type, new Name(localName, staticName), exclusive, fallback));
this.entries.put(type, new Entry(type, new Name(localName, staticName), exclusive, inherit, fallback));
}
default -> reader.skipValue();
}
Expand Down Expand Up @@ -154,9 +156,9 @@ private List<Name> collectFallbacks(JsonReader reader, String type) throws IOExc
return list;
}

public record Entry(String type, Name name, boolean exclusive, List<Name> fallback) {
public record Entry(String type, Name name, boolean exclusive, boolean inherit, List<Name> fallback) {
public Entry(String type, String localName, String staticName) {
this(type, new Name(localName, staticName), false, Collections.emptyList());
this(type, new Name(localName, staticName), false, false, Collections.emptyList());
}

public @Nullable Name findFallback(Predicate<Name> predicate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package org.quiltmc.enigma_plugin.index.simple_type_single;

import org.quiltmc.enigma.api.analysis.index.jar.InheritanceIndex;
import org.quiltmc.enigma.api.analysis.index.jar.JarIndex;
import org.quiltmc.enigma.api.class_provider.ClassProvider;
import org.quiltmc.enigma.api.service.EnigmaServiceContext;
import org.quiltmc.enigma.api.service.JarIndexerService;
Expand Down Expand Up @@ -56,6 +58,8 @@ public class SimpleTypeSingleIndex extends Index {
private final Map<ClassNode, Map<String, FieldBuildingEntry>> fieldCache = new HashMap<>();
private SimpleTypeFieldNamesRegistry registry;

private InheritanceIndex inheritance;

public SimpleTypeSingleIndex() {
super(null);
}
Expand All @@ -68,6 +72,11 @@ public void withContext(EnigmaServiceContext<JarIndexerService> context) {
.map(context::getPath).orElse(null));
}

@Override
public void setIndexingContext(Set<String> classes, JarIndex jarIndex) {
this.inheritance = jarIndex.getIndex(InheritanceIndex.class);
}

public void loadRegistry(Path path) {
if (path == null) {
this.registry = null;
Expand Down Expand Up @@ -195,7 +204,7 @@ private Map<String, FieldBuildingEntry> collectMatchingFields(ClassProvider clas
if (field.desc.charAt(0) != 'L') continue;
String type = field.desc.substring(1, field.desc.length() - 1);

var entry = this.registry.getEntry(type);
var entry = this.getEntry(type);
if (entry != null) {
// Check if there's a field by the default name
var existingEntry = knownFields.get(entry.name().local());
Expand Down Expand Up @@ -257,7 +266,7 @@ private Map<String, ParameterBuildingEntry> collectMatchingParameters(MethodNode
if (desc.charAt(0) != 'L') continue;
String type = desc.substring(1, desc.length() - 1);

var entry = this.registry.getEntry(type);
var entry = this.getEntry(type);
if (entry != null) {
ParameterBuildingEntry existingEntry = knownParameters.get(entry.name().local());

Expand Down Expand Up @@ -297,6 +306,28 @@ private Map<String, ParameterBuildingEntry> collectMatchingParameters(MethodNode
return knownParameters;
}

@Nullable
private SimpleTypeFieldNamesRegistry.Entry getEntry(String type) {
// Default to returning this if it is specified
var entry = this.registry.getEntry(type);

if (entry != null) {
return entry;
}

// Check all parent classes for an entry. This goes in order of super/interface, supersuper/interfacesuper, etc
for (ClassEntry ancestor : this.inheritance.getAncestors(new ClassEntry(type))) {
entry = this.registry.getEntry(ancestor.getFullName());

// Only return if the entry allows inheritance
if (entry != null && entry.inherit()) {
return entry;
}
}

return null;
}

private record FieldBuildingEntry(FieldNode node, Name name, SimpleTypeFieldNamesRegistry.Entry entry) {
public static FieldBuildingEntry createNull(SimpleTypeFieldNamesRegistry.Entry entry) {
return new FieldBuildingEntry(null, null, entry);
Expand Down
26 changes: 26 additions & 0 deletions src/test/java/org/quiltmc/enigma_plugin/NameProposalTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ public void testSimpleTypeSingleNames() {
assertProposal("valueC", field(owner, "h", "Lcom/a/b/i;"));

owner = new ClassEntry(fieldsClassEntry, "c");
assertProposal("valueD", field(owner, "a", "Lcom/a/b/k;"));
assertNotProposed(field(owner, "b", "Lcom/a/b/m;"));

owner = new ClassEntry(fieldsClassEntry, "d");
assertProposal("CONFIG", field(owner, "a", "Lcom/a/b/a;"));
assertProposal("STATIC_STATE", field(owner, "b", "Lcom/a/b/e;"));
assertProposal("value", field(owner, "c", "Lcom/a/b/i;"));
Expand Down Expand Up @@ -261,6 +265,28 @@ public void testSimpleTypeSingleNames() {
parent = method(owner, "a", "(Lcom/a/b/g;Lcom/a/b/g;)V");
assertNotProposed(localVar(parent, 0));
assertNotProposed(localVar(parent, 1));

// Check that both the parent and child class have names
parent = method(owner, "a", "(Lcom/a/b/j;)V");
assertProposal("valueD", localVar(parent, 0));

parent = method(owner, "a", "(Lcom/a/b/k;)V");
assertProposal("valueD", localVar(parent, 0));

// Check that just the parent class has a name
parent = method(owner, "a", "(Lcom/a/b/l;)V");
assertProposal("valueE", localVar(parent, 0));

parent = method(owner, "a", "(Lcom/a/b/m;)V");
assertNotProposed(localVar(parent, 0));

// Check that indexing order doesn't affect inheritance tree
owner = new ClassEntry("com/a/b/j");
parent = method(owner, "a", "(Lcom/a/b/j;)V");
assertProposal("valueD", localVar(parent, 0));

parent = method(owner, "a", "(Lcom/a/b/k;)V");
assertProposal("valueD", localVar(parent, 0));
}

@Test
Expand Down
21 changes: 21 additions & 0 deletions src/testInputs/java/com/example/SimpleTypeNamesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import com.example.simple_type_names.ValueA;
import com.example.simple_type_names.ValueB;
import com.example.simple_type_names.ValueC;
import com.example.simple_type_names.ValueD;
import com.example.simple_type_names.ValueDD;
import com.example.simple_type_names.ValueE;
import com.example.simple_type_names.ValueEE;

public class SimpleTypeNamesTest {
public static class Fields {
Expand All @@ -30,6 +34,11 @@ public static class Fallbacks {
public final ValueC valueC = new ValueC();
}

public static class Inheritance {
public final ValueDD valueD = new ValueDD();
public final ValueEE valueE = new ValueEE();
}

public static class Unique {
public static final Config CONFIG = new Config();
public static final StateA STATIC_STATE = new StateA();
Expand Down Expand Up @@ -64,5 +73,17 @@ public static void value(ValueA valueA, ValueB valueB, ValueC valueC) {

public static void value(ValueA unnamedValueA, ValueA unnamedValueA2) {
}

public static void value(ValueD valueD) {
}

public static void value(ValueDD valueD) {
}

public static void value(ValueE valueD) {
}

public static void value(ValueEE valueD) {
}
}
}
9 changes: 9 additions & 0 deletions src/testInputs/java/com/example/simple_type_names/ValueD.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.example.simple_type_names;

public class ValueD {
public static void value(ValueD valueD) {
}

public static void value(ValueDD valueD) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.simple_type_names;

public class ValueDD extends ValueD {
}
4 changes: 4 additions & 0 deletions src/testInputs/java/com/example/simple_type_names/ValueE.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.simple_type_names;

public class ValueE {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.simple_type_names;

public class ValueEE extends ValueE {
}
9 changes: 9 additions & 0 deletions src/testInputs/resources/simple_type_field_names.json5
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,14 @@
fallback: [
"valueC"
]
},
"com/a/b/j": { // ValueD
local_name: "valueD",
exclusive: true,
inherit: true
},
"com/a/b/l": { // ValueE
local_name: "valueE",
exclusive: true
}
}

0 comments on commit 80f1c3e

Please sign in to comment.