From 626a2983f14aff02fe61231bee6d04fb47a27b44 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Mon, 29 Apr 2019 19:37:39 +0200 Subject: Prevent local variables from shadowing of implicit member references E.g. `Entity#posX` is remapped to `x` which may then be shadowed by a local variable with the same name. Since I cannot figure out how to get JDT to give me a list of all variables in scope at a particular node, the solution employed is to just forbid any implicit references to remapped members. This finds quite a few false positives (but not too many to manually deal with), so I'd be quite happy to switch to another solution if one becomes available. --- .../com/replaymod/gradle/remap/Transformer.java | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/replaymod/gradle/remap/Transformer.java b/src/main/java/com/replaymod/gradle/remap/Transformer.java index 02075bc..0cb9afe 100644 --- a/src/main/java/com/replaymod/gradle/remap/Transformer.java +++ b/src/main/java/com/replaymod/gradle/remap/Transformer.java @@ -28,6 +28,7 @@ import java.util.stream.Collectors; class Transformer { private Map map; private String[] classpath; + private boolean fail; public static void main(String[] args) throws IOException, BadLocationException { Map mappings; @@ -72,6 +73,10 @@ class Transformer { System.out.println(line); } } + + if (transformer.fail) { + System.exit(1); + } } public Transformer(Map mappings) { @@ -135,7 +140,7 @@ class Transformer { CompilationUnit cu = entry.getValue(); cu.recordModifications(); - if (remapClass(cu)) { + if (remapClass(unitName, cu)) { Document document = new Document(sources.get(unitName)); TextEdit edit = cu.rewrite(document, JavaCore.getDefaultOptions()); edit.apply(document); @@ -372,7 +377,7 @@ class Transformer { return paramIndex != -1 ? name.substring(0, paramIndex) : name; } - private boolean remapClass(CompilationUnit cu) { + private boolean remapClass(String unitName, CompilationUnit cu) { AtomicBoolean changed = new AtomicBoolean(false); Map mappedImports = new HashMap<>(); Map mixinMappings = new HashMap<>(); @@ -484,6 +489,19 @@ class Transformer { } if (mapping == null) return true; mapped = mapping.fields.get(node.getIdentifier()); + if (mapped != null) { + ASTNode parent = node.getParent(); + if (!(parent instanceof FieldAccess // qualified access is fine + || parent instanceof QualifiedName // qualified access is fine + || parent instanceof VariableDeclarationFragment // shadow member declarations are fine + || parent instanceof SwitchCase) // referencing constants in case statements is fine + ) { + System.err.println(unitName + ": Implicit member reference to remapped field \"" + node.getIdentifier() + "\". " + + "This can cause issues if the remapped reference becomes shadowed by a local variable and is therefore forbidden. " + + "Use \"this." + node.getIdentifier() + "\" instead."); + fail = true; + } + } } else if (binding instanceof IMethodBinding) { ITypeBinding declaringClass = ((IMethodBinding) binding).getDeclaringClass(); if (declaringClass == null) return true; -- cgit