Class: Squash::Java::Namespace
- Inherits:
-
Object
- Object
- Squash::Java::Namespace
- Defined in:
- lib/squash/java/namespace.rb
Overview
A Ruby representation of the packages, classes, methods, and fields of a Java project, with their full and obfuscated names. The RenameLog class loads a Namespace from a yGuard or ProGuard rename log file.
Note: Some of the finder methods of this class and its enclosed classes are find-or-create-type methods. Read the method documentation for each method carefully.
**Another note:** A distinction is made between full and partial names (e.g., “MyClass” vs. “com.mycompany.MyClass”), and cleartext and obfuscated names (e.g., “com.mycompany.MyClass” vs. “com.A.B”). Note that there are four possible combinations of these states. Method docs will state what naming format is expected for each parameter.
Constant Summary collapse
- METHOD_REGEX =
/^([a-z0-9_.$\[\]]+) ([a-z0-9_$]+)\(([a-z$0-9_.\[\] ,]*)\)/i
Instance Method Summary collapse
-
#add_class_alias(name, obfuscation) ⇒ Squash::Java::Class
Associates a full class name with an obfuscated name.
-
#add_method_alias(class_or_name, method_name, obfuscation) ⇒ Squash::Java::Method
Associates a method name with an obfuscated alias.
-
#add_package_alias(name, obfuscation) ⇒ Squash::Java::Package
Associates a full package name with an obfuscated name.
-
#argument(type_descriptor) ⇒ Squash::Java::Argument
Creates a new Argument for a given type descriptor.
-
#find_files(root) ⇒ Object
Attempts to locate the paths to the Classes defined in this Namespace.
-
#initialize ⇒ Namespace
constructor
Creates a new empty Namespace.
-
#java_method(klass, name) ⇒ Squash::Java::Method
**Finds or creates** a method by its name and parent class.
-
#obfuscated_argument(type_descriptor) ⇒ Squash::Java::Argument?
Creates a new Argument for a given type descriptor, which can be fully or partially obfuscated.
-
#obfuscated_class(identifier) ⇒ Squash::Java::Class?
Finds a class by its obfuscated (or partially obfuscated) full name.
-
#obfuscated_method(klass, name) ⇒ Squash::Java::Method?
Finds a method by its obfuscated name and parent class.
-
#obfuscated_package(identifier) ⇒ Squash::Java::Package?
Finds a package by its obfuscated (or partially obfuscated) full name.
-
#obfuscated_type(name) ⇒ Squash::Java::Type?
Finds a class or primitive type by its obfuscated name.
-
#package(identifier) ⇒ Squash::Java::Package
(also: #klass)
**Finds or creates** a package by its full name.
-
#path_for_class(klass) ⇒ String?
Returns the path to a Class‘s source .java file, relative to the project root, if a) the class exists in the namespace, and b) the class has a known path.
-
#type(name) ⇒ Squash::Java::Type
**Finds or creates** a primitive or class type by its name.
Constructor Details
#initialize ⇒ Namespace
Creates a new empty Namespace.
39 40 41 |
# File 'lib/squash/java/namespace.rb', line 39 def initialize @package_roots = Set.new end |
Instance Method Details
#add_class_alias(name, obfuscation) ⇒ Squash::Java::Class
Associates a full class name with an obfuscated name.
114 115 116 117 118 |
# File 'lib/squash/java/namespace.rb', line 114 def add_class_alias(name, obfuscation) cl = klass(name) cl.obfuscation = obfuscation return cl end |
#add_method_alias(class_or_name, method_name, obfuscation) ⇒ Squash::Java::Method
Associates a method name with an obfuscated alias.
128 129 130 131 132 133 |
# File 'lib/squash/java/namespace.rb', line 128 def add_method_alias(class_or_name, method_name, obfuscation) cl = (class_or_name.kind_of?(Squash::Java::Class) ? class_or_name : klass(class_or_name)) meth = java_method(cl, method_name) meth.obfuscation = obfuscation return meth end |
#add_package_alias(name, obfuscation) ⇒ Squash::Java::Package
Associates a full package name with an obfuscated name.
101 102 103 104 105 |
# File 'lib/squash/java/namespace.rb', line 101 def add_package_alias(name, obfuscation) pkg = package(name) pkg.obfuscation = obfuscation return pkg end |
#argument(type_descriptor) ⇒ Squash::Java::Argument
Creates a new Argument for a given type descriptor. This can be a primitive (e.g., “float”) or a full class name (e.g., “com.foo.Bar”), and can be a scalar or an array (e.g., “float[]” or “com.foo.Bar[]”). **Finds or creates** the Type, and **always creates** a new Argument.
261 262 263 264 265 |
# File 'lib/squash/java/namespace.rb', line 261 def argument(type_descriptor) dimensionality = type_descriptor.scan(/\[\]/).size type_name = type_descriptor.gsub(/\[\]/, '') Squash::Java::Argument.new type(type_name), dimensionality end |
#find_files(root) ⇒ Object
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/squash/java/namespace.rb', line 58 def find_files(root, package_or_class=nil) case package_or_class when nil root.sub! /\/$/, '' @package_roots.each { |pkg| find_files root, pkg } when Squash::Java::Package package_or_class.classes.each { |cl| find_files root, cl } package_or_class.children.each { |pkg| find_files root, pkg } when Squash::Java::Class class_subpath = package_or_class.subpath Find.find(root) do |project_path| if project_path[0, root.length + 2] == root + '/.' Find.prune next end if project_path[-class_subpath.length, class_subpath.length] == class_subpath package_or_class.path = project_path.sub(/^#{Regexp.escape root}\//, '') end end end end |
#java_method(klass, name) ⇒ Squash::Java::Method
**Finds or creates** a method by its name and parent class. Polymorphism is supported: Two methods can share the same name so long as their argument count or types are different.
222 223 224 225 226 227 228 229 230 231 |
# File 'lib/squash/java/namespace.rb', line 222 def java_method(klass, name) matches = name.match(METHOD_REGEX) or raise "Invalid method name #{name.inspect}" return_type = argument(matches[1]) method_name = matches[2] args = matches[3].split(/,\s*/).map { |arg| argument(arg) } args = [] if matches[3].empty? klass.java_methods.detect { |meth| meth.name == method_name && meth.arguments == args } || Squash::Java::Method.new(klass, method_name, return_type, *args) end |
#obfuscated_argument(type_descriptor) ⇒ Squash::Java::Argument?
Creates a new Argument for a given type descriptor, which can be fully or partially obfuscated. This can be an unobfuscated primitive (e.g., “float”) or a possibly-obfuscated full class name (e.g., “com.foo.A”), and can be a scalar or an array (e.g., “float[]” or “com.foo.A[]”). Finds the Type, and **always creates** a new Argument. Returns ‘nil` for unknown types.
278 279 280 281 282 283 284 |
# File 'lib/squash/java/namespace.rb', line 278 def (type_descriptor) dimensionality = type_descriptor.scan(/\[\]/).size type_name = type_descriptor.gsub(/\[\]/, '') type = (type_name) return nil unless type Squash::Java::Argument.new type, dimensionality end |
#obfuscated_class(identifier) ⇒ Squash::Java::Class?
Finds a class by its obfuscated (or partially obfuscated) full name. (Technically it also works as a find-only variant of #klass since all some, or none of the name need be obfuscated.)
184 185 186 187 188 189 190 191 |
# File 'lib/squash/java/namespace.rb', line 184 def (identifier) parts = identifier.split('.') class_name = parts.pop pkg = (parts.join('.')) return nil unless pkg pkg.classes.detect { |cl| cl.obfuscation == class_name || cl.name == class_name } end |
#obfuscated_method(klass, name) ⇒ Squash::Java::Method?
Finds a method by its obfuscated name and parent class. Polymorphism is supported: Two methods can share the same name so long as their argument count or types are different.
242 243 244 245 246 247 248 249 |
# File 'lib/squash/java/namespace.rb', line 242 def (klass, name) matches = name.match(METHOD_REGEX) or raise "Invalid method name #{name.inspect}" return_type = (matches[1]) method_name = matches[2] args = matches[3].split(/,\s*/).map { |arg| (arg) } args = [] if matches[3].empty? klass.java_methods.detect { |m| m.obfuscation == method_name && m.arguments == args } end |
#obfuscated_package(identifier) ⇒ Squash::Java::Package?
Finds a package by its obfuscated (or partially obfuscated) full name. (Technically it also works as a find-only variant of #package since all, some, or none of the name need be obfuscated.)
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/squash/java/namespace.rb', line 165 def (identifier) parts = identifier.split('.') root_name = parts.shift root = @package_roots.detect { |pkg| pkg.name == root_name } if parts.empty? root else root ? root.(parts.join('.')) : nil end end |
#obfuscated_type(name) ⇒ Squash::Java::Type?
Finds a class or primitive type by its obfuscated name. Primitives are never obfuscated.
209 210 211 |
# File 'lib/squash/java/namespace.rb', line 209 def (name) Squash::Java::PRIMITIVES.detect { |prim| prim.name == name } || (name) end |
#package(identifier) ⇒ Squash::Java::Package Also known as: klass
**Finds or creates** a package by its full name.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/squash/java/namespace.rb', line 140 def package(identifier) parts = identifier.split('.') root_name = parts.shift root = @package_roots.detect { |pkg| pkg.name == root_name } || begin pkg = Squash::Java::Package.new(root_name) @package_roots << pkg pkg end if parts.empty? root else root.find_or_create(parts.join('.')) end end |
#path_for_class(klass) ⇒ String?
Returns the path to a Class‘s source .java file, relative to the project root, if a) the class exists in the namespace, and b) the class has a known path.
89 90 91 92 |
# File 'lib/squash/java/namespace.rb', line 89 def path_for_class(klass) cl = (klass) cl ? cl.path : nil end |
#type(name) ⇒ Squash::Java::Type
**Finds or creates** a primitive or class type by its name.
198 199 200 |
# File 'lib/squash/java/namespace.rb', line 198 def type(name) Squash::Java::PRIMITIVES.detect { |prim| prim.name == name } || klass(name) end |