summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/Ancestries.java
diff options
context:
space:
mode:
authorGravatar jeff2014-08-26 00:27:44 -0400
committerGravatar jeff2014-08-26 00:27:44 -0400
commit5f44aac70f59898197c2a7625b74f901c3b31106 (patch)
tree7d2cc2e48201c92867786793966f356810b464fa /src/cuchaz/enigma/analysis/Ancestries.java
parentwrote CheckCastIterator to try to do generic type inference. It's too hard to... (diff)
downloadenigma-fork-5f44aac70f59898197c2a7625b74f901c3b31106.tar.gz
enigma-fork-5f44aac70f59898197c2a7625b74f901c3b31106.tar.xz
enigma-fork-5f44aac70f59898197c2a7625b74f901c3b31106.zip
implemented proper support for interfaces
Diffstat (limited to 'src/cuchaz/enigma/analysis/Ancestries.java')
-rw-r--r--src/cuchaz/enigma/analysis/Ancestries.java89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/analysis/Ancestries.java b/src/cuchaz/enigma/analysis/Ancestries.java
index b9d8cbf..9724108 100644
--- a/src/cuchaz/enigma/analysis/Ancestries.java
+++ b/src/cuchaz/enigma/analysis/Ancestries.java
@@ -11,24 +11,32 @@
11package cuchaz.enigma.analysis; 11package cuchaz.enigma.analysis;
12 12
13import java.io.Serializable; 13import java.io.Serializable;
14import java.util.AbstractMap;
14import java.util.ArrayList; 15import java.util.ArrayList;
16import java.util.HashSet;
15import java.util.List; 17import java.util.List;
16import java.util.Map; 18import java.util.Map;
19import java.util.Set;
17 20
18import javassist.bytecode.Descriptor; 21import javassist.bytecode.Descriptor;
19 22
23import com.google.common.collect.HashMultimap;
20import com.google.common.collect.Lists; 24import com.google.common.collect.Lists;
21import com.google.common.collect.Maps; 25import com.google.common.collect.Maps;
26import com.google.common.collect.Multimap;
27import com.google.common.collect.Sets;
22 28
23public class Ancestries implements Serializable 29public class Ancestries implements Serializable
24{ 30{
25 private static final long serialVersionUID = 738687982126844179L; 31 private static final long serialVersionUID = 738687982126844179L;
26 32
27 private Map<String,String> m_superclasses; 33 private Map<String,String> m_superclasses;
34 private Multimap<String,String> m_interfaces;
28 35
29 public Ancestries( ) 36 public Ancestries( )
30 { 37 {
31 m_superclasses = Maps.newHashMap(); 38 m_superclasses = Maps.newHashMap();
39 m_interfaces = HashMultimap.create();
32 } 40 }
33 41
34 public void addSuperclass( String className, String superclassName ) 42 public void addSuperclass( String className, String superclassName )
@@ -47,8 +55,25 @@ public class Ancestries implements Serializable
47 } 55 }
48 } 56 }
49 57
58 public void addInterface( String className, String interfaceName )
59 {
60 className = Descriptor.toJvmName( className );
61 interfaceName = Descriptor.toJvmName( interfaceName );
62
63 if( className.equals( interfaceName ) )
64 {
65 throw new IllegalArgumentException( "Class cannot be its own interface! " + className );
66 }
67
68 if( !isJre( className ) && !isJre( interfaceName ) )
69 {
70 m_interfaces.put( className, interfaceName );
71 }
72 }
73
50 public void renameClasses( Map<String,String> renames ) 74 public void renameClasses( Map<String,String> renames )
51 { 75 {
76 // rename superclasses
52 Map<String,String> newSuperclasses = Maps.newHashMap(); 77 Map<String,String> newSuperclasses = Maps.newHashMap();
53 for( Map.Entry<String,String> entry : m_superclasses.entrySet() ) 78 for( Map.Entry<String,String> entry : m_superclasses.entrySet() )
54 { 79 {
@@ -65,6 +90,28 @@ public class Ancestries implements Serializable
65 newSuperclasses.put( subclass, superclass ); 90 newSuperclasses.put( subclass, superclass );
66 } 91 }
67 m_superclasses = newSuperclasses; 92 m_superclasses = newSuperclasses;
93
94 // rename interfaces
95 Set<Map.Entry<String,String>> entriesToAdd = Sets.newHashSet();
96 for( Map.Entry<String,String> entry : m_interfaces.entries() )
97 {
98 String className = renames.get( entry.getKey() );
99 if( className == null )
100 {
101 className = entry.getKey();
102 }
103 String interfaceName = renames.get( entry.getValue() );
104 if( interfaceName == null )
105 {
106 interfaceName = entry.getValue();
107 }
108 entriesToAdd.add( new AbstractMap.SimpleEntry<String,String>( className, interfaceName ) );
109 }
110 m_interfaces.clear();
111 for( Map.Entry<String,String> entry : entriesToAdd )
112 {
113 m_interfaces.put( entry.getKey(), entry.getValue() );
114 }
68 } 115 }
69 116
70 public String getSuperclassName( String className ) 117 public String getSuperclassName( String className )
@@ -86,6 +133,17 @@ public class Ancestries implements Serializable
86 return ancestors; 133 return ancestors;
87 } 134 }
88 135
136 public Set<String> getInterfaces( String className )
137 {
138 Set<String> interfaceNames = new HashSet<String>();
139 interfaceNames.addAll( m_interfaces.get( className ) );
140 for( String ancestor : getAncestry( className ) )
141 {
142 interfaceNames.addAll( m_interfaces.get( ancestor ) );
143 }
144 return interfaceNames;
145 }
146
89 public List<String> getSubclasses( String className ) 147 public List<String> getSubclasses( String className )
90 { 148 {
91 // linear search is fast enough for now 149 // linear search is fast enough for now
@@ -102,6 +160,37 @@ public class Ancestries implements Serializable
102 return subclasses; 160 return subclasses;
103 } 161 }
104 162
163 public Set<String> getImplementingClasses( String targetInterfaceName )
164 {
165 // linear search is fast enough for now
166 Set<String> classNames = Sets.newHashSet();
167 for( Map.Entry<String,String> entry : m_interfaces.entries() )
168 {
169 String className = entry.getKey();
170 String interfaceName = entry.getValue();
171 if( interfaceName.equals( targetInterfaceName ) )
172 {
173 classNames.add( className );
174 collectSubclasses( classNames, className );
175 }
176 }
177 return classNames;
178 }
179
180 public boolean isInterface( String className )
181 {
182 return m_interfaces.containsValue( className );
183 }
184
185 private void collectSubclasses( Set<String> classNames, String className )
186 {
187 for( String subclassName : getSubclasses( className ) )
188 {
189 classNames.add( subclassName );
190 collectSubclasses( classNames, subclassName );
191 }
192 }
193
105 private boolean isJre( String className ) 194 private boolean isJre( String className )
106 { 195 {
107 return className.startsWith( "java/" ) 196 return className.startsWith( "java/" )