prevent static field name clashes in local methods
This commit is contained in:
@@ -28,9 +28,9 @@ import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
|
|||||||
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||||
import org.jetbrains.java.decompiler.struct.match.MatchEngine;
|
import org.jetbrains.java.decompiler.struct.match.MatchEngine;
|
||||||
import org.jetbrains.java.decompiler.struct.match.MatchNode;
|
import org.jetbrains.java.decompiler.struct.match.MatchNode;
|
||||||
import org.jetbrains.java.decompiler.struct.match.IMatchable.MatchProperties;
|
|
||||||
import org.jetbrains.java.decompiler.struct.match.MatchNode.RuleValue;
|
import org.jetbrains.java.decompiler.struct.match.MatchNode.RuleValue;
|
||||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||||
|
import org.jetbrains.java.decompiler.util.StructUtils;
|
||||||
import org.jetbrains.java.decompiler.util.TextUtil;
|
import org.jetbrains.java.decompiler.util.TextUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -84,13 +84,17 @@ public class FieldExprent extends Exprent {
|
|||||||
return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor, bytecode);
|
return new FieldExprent(name, classname, isStatic, instance == null ? null : instance.copy(), descriptor, bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAmbiguous() {
|
||||||
|
return StructUtils.getCurrentMethodLocalVariableNames().contains(name);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
|
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
|
||||||
TextBuffer buf = new TextBuffer();
|
TextBuffer buf = new TextBuffer();
|
||||||
|
|
||||||
if (isStatic) {
|
if (isStatic) {
|
||||||
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
||||||
if (node == null || !classname.equals(node.classStruct.qualifiedName)) {
|
if (node == null || !classname.equals(node.classStruct.qualifiedName) || isAmbiguous()) {
|
||||||
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(classname)));
|
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(classname)));
|
||||||
buf.append(".");
|
buf.append(".");
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/org/jetbrains/java/decompiler/util/StructUtils.java
Normal file
65
src/org/jetbrains/java/decompiler/util/StructUtils.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.java.decompiler.util;
|
||||||
|
|
||||||
|
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||||||
|
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
|
||||||
|
import org.jetbrains.java.decompiler.struct.StructMember;
|
||||||
|
import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
|
||||||
|
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.jetbrains.java.decompiler.main.DecompilerContext.CURRENT_METHOD_WRAPPER;
|
||||||
|
import static org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute.ATTRIBUTE_LOCAL_VARIABLE_TABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alexandru-Constantin Bledea
|
||||||
|
* @since March 07, 2016
|
||||||
|
*/
|
||||||
|
public final class StructUtils {
|
||||||
|
|
||||||
|
private StructUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the local variables of the current method
|
||||||
|
*/
|
||||||
|
public static List<String> getCurrentMethodLocalVariableNames() {
|
||||||
|
final MethodWrapper method = (MethodWrapper) DecompilerContext.getProperty(CURRENT_METHOD_WRAPPER);
|
||||||
|
if (null == method) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return getLocalVariables(method.methodStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param structMember the struct member from which to extract the local variables
|
||||||
|
* @return the local variables of the struct member
|
||||||
|
*/
|
||||||
|
public static List<String> getLocalVariables(final StructMember structMember) {
|
||||||
|
final VBStyleCollection<StructGeneralAttribute, String> methodStruct = structMember.getAttributes();
|
||||||
|
final StructGeneralAttribute generalAttribute = methodStruct.getWithKey(ATTRIBUTE_LOCAL_VARIABLE_TABLE);
|
||||||
|
if (generalAttribute instanceof StructLocalVariableTableAttribute) {
|
||||||
|
final StructLocalVariableTableAttribute table = (StructLocalVariableTableAttribute) generalAttribute;
|
||||||
|
return Collections.unmodifiableList(new ArrayList<>(table.getMapVarNames().values()));
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -82,6 +82,7 @@ public class SingleClassesTest {
|
|||||||
@Test public void testMethodReferenceSameName() { doTest("pkg/TestMethodReferenceSameName"); }
|
@Test public void testMethodReferenceSameName() { doTest("pkg/TestMethodReferenceSameName"); }
|
||||||
@Test public void testMethodReferenceLetterClass() { doTest("pkg/TestMethodReferenceLetterClass"); }
|
@Test public void testMethodReferenceLetterClass() { doTest("pkg/TestMethodReferenceLetterClass"); }
|
||||||
@Test public void testMemberAnnotations() { doTest("pkg/TestMemberAnnotations"); }
|
@Test public void testMemberAnnotations() { doTest("pkg/TestMemberAnnotations"); }
|
||||||
|
@Test public void testStaticNameClash() { doTest("pkg/TestStaticNameClash"); }
|
||||||
|
|
||||||
protected void doTest(String testFile, String... companionFiles) {
|
protected void doTest(String testFile, String... companionFiles) {
|
||||||
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
ConsoleDecompiler decompiler = fixture.getDecompiler();
|
||||||
|
|||||||
BIN
testData/classes/pkg/TestStaticNameClash.class
Normal file
BIN
testData/classes/pkg/TestStaticNameClash.class
Normal file
Binary file not shown.
20
testData/results/TestStaticNameClash.dec
Normal file
20
testData/results/TestStaticNameClash.dec
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
public class TestStaticNameClash {
|
||||||
|
public static String property;
|
||||||
|
|
||||||
|
public static void setProperty(String property) {
|
||||||
|
TestStaticNameClash.property = property;// 12
|
||||||
|
}// 13
|
||||||
|
}
|
||||||
|
|
||||||
|
class 'pkg/TestStaticNameClash' {
|
||||||
|
method 'setProperty (Ljava/lang/String;)V' {
|
||||||
|
1 6
|
||||||
|
4 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lines mapping:
|
||||||
|
12 <-> 7
|
||||||
|
13 <-> 8
|
||||||
15
testData/src/pkg/TestStaticNameClash.java
Normal file
15
testData/src/pkg/TestStaticNameClash.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package pkg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Alexandru-Constantin Bledea
|
||||||
|
* @since March 07, 2016
|
||||||
|
*/
|
||||||
|
public class TestStaticNameClash {
|
||||||
|
|
||||||
|
public static String property;
|
||||||
|
|
||||||
|
public static void setProperty(final String property) {
|
||||||
|
TestStaticNameClash.property = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user