def is_assignable(self, lhs, rhs): if lhs == "void": return False if lhs == rhs: return True can_assign_arrays_to = ["java.lang.Object", "java.io.Serializable", "java.lang.Cloneable"] if lhs in can_assign_arrays_to and isarray(rhs): return True if isarray(lhs) and isarray(rhs): lhs = lhs[:-2] rhs = rhs[:-2] if lhs == rhs: return True if is_primitive(lhs) or is_primitive(rhs): return False return self.is_assignable(lhs, rhs) if isarray(rhs): return False if rhs == "null" and not is_primitive(lhs): return True if is_primitive(lhs) or is_primitive(rhs): return self.is_primitive_assignable(lhs, rhs) else: if rhs == "null": return True return self.is_supertype(lhs, rhs)
def relational_expression(element): lhs_type = element.env.canonicalize_name(element[0].attrib['type']) rhs_type = element.env.canonicalize_name(element[2].attrib['type']) if element[1].text in ["<", ">", "<=", ">="]: error_if(not (is_integral_primitive(lhs_type) and is_integral_primitive(rhs_type)), "Relational expression passed non-integral types.") elif element[1].text == "instanceof": error_if(is_primitive(lhs_type) or is_primitive(rhs_type), "Cannot have primitives in instanceof") element.attrib["type"] = "boolean"
def method_invocation(element): if element[0].tag == "name": name = name_to_str(element.find("name")) to_file(element) declaration_site = element.env.get_declaration_site_for_method_name( name, argument_list(element)) element.attrib["type"] = element.env.get_type_for_declaration_site( declaration_site) element.declaration = declaration_site elif element[0].tag == "primary": primary_type = element[0].attrib["type"] error_if(is_primitive(primary_type), "Cannot invoke method on primitive " + primary_type) declaration_site = element.env.get_declaration_site_for_class_name( primary_type) identifier = element.find("tok_identifier").text method_declaration = \ declaration_site.env.get_declaration_site_for_method_name( identifier, argument_list(element)) element.attrib["type"] = \ method_declaration.env.get_type_for_declaration_site( method_declaration) element.declaration = method_declaration else: assert False
def get_type_for_declaration_site(self, element): decl_type_string = type_string(element) if (is_primitive(decl_type_string) or isarray(decl_type_string) or decl_type_string == "void"): return decl_type_string return self.findclass(decl_type_string).get("canonical_name")
def step(sprops, dprops): for name, prop in sprops.iteritems(): if not check(name, prop, dprops): return if util.is_primitive(prop) or util.is_from_group(prop): value = util.get_value(prop) if name not in dprops: dprops[name] = util.ValueFromGroup(value, src, depth) elif util.is_from_group(dprops[name]): if util.get_depth(dprops[name]) == depth: errors.append(MergeError( ('value for "%s" is absent in "%s" but ' + 'came from two diffrent groups: "%s" and "%s", ' + 'can\'t merge') % (name, dst, src, dprops[name].source))) elif util.get_depth(dprops[name]) > depth: dprops[name] = util.ValueFromGroup(value, src, depth) elif type(prop) == list: dprops[name] = (merge_lists(prop, dprops[name]) if name in dprops else prop) elif type(prop) == dict: dprops[name] = (step(prop, dprops[name]) if name in dprops else prop) else: errors.append(MergeError('unknown type of prop %s (%s), ' + 'can\'t merge' % (name, type(prop)))) return dprops
def is_subtype(self, obj1, obj2): """Returns whether obj1 is a subclass of obj2.""" assert not is_primitive(obj1) assert not is_primitive(obj2) if isarray(obj1) and isarray(obj2): obj1 = obj1[:-2] obj2 = obj2[:-2] elif isarray(obj1): if obj2 == "java.lang.Object": return True else: return False obj1 = self.findclass(obj1) obj2 = self.findclass(obj2) return self.is_classes_subtype(obj1, obj2)
def step(attr): if util.is_primitive(attr) or util.is_from_group(attr): return util.get_value(attr) elif type(attr) == list: return map(step, attr) elif type(attr) == dict: for key in attr.iterkeys(): attr[key] = step(attr[key]) return attr else: assert False, "unknown type %s" % type(attr)
def is_classes_subtype(self, obj1, obj2): if obj1 is obj2: return True if obj1 == "null" and not is_primitive(obj2): return True for clazz in [obj1.superclass] + obj1.interfaces: if clazz is obj2: return True if clazz is not self.findclass("java.lang.Object"): if self.is_classes_subtype(clazz, obj2): return True return False
def field_access(element): primary_type = element[0].attrib["type"] error_if(is_primitive(primary_type), "No fields on primitive type.") declaration_site = \ element.env.get_declaration_site_for_class_name(primary_type) identifier = element.find("tok_identifier").text secondary_site = \ declaration_site.env.get_declaration_site_for_variable_name(identifier, element.find("tok_identifier")) secondary_type = \ secondary_site.env.get_type_for_declaration_site(secondary_site) element.attrib["type"] = secondary_type element.declaration = secondary_site
def are_identity_comparable(self, obj1, obj2): """Returns whether obj1 and obj2 can occur in an == expression.""" if obj1 == "null" or obj2 in ["null", "void", "void"]: return True if is_integral_primitive(obj1) ^ is_integral_primitive(obj2): return False if is_integral_primitive(obj1) and is_integral_primitive(obj2): return True if is_primitive(obj1) and obj1 == obj2: return True if self.is_subtype(obj1, obj2) or self.is_subtype(obj2, obj1): return True return False
def _get_flattener(self, obj): if util.is_primitive(obj): return lambda obj: obj list_recurse = self._list_recurse if util.is_list(obj): if self._mkref(obj): return list_recurse else: self._push() return self._getref # We handle tuples and sets by encoding them in a "(tuple|set)dict" if util.is_tuple(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.TUPLE: [self._flatten(v) for v in obj]} if util.is_set(obj): if not self.unpicklable: return list_recurse return lambda obj: {tags.SET: [self._flatten(v) for v in obj]} if util.is_dictionary(obj): return self._flatten_dict_obj if util.is_type(obj): return _mktyperef if util.is_object(obj): return self._ref_obj_instance # else, what else? (methods, functions, old style classes...) return None
def is_primitive_variable_declaration_site(element): return is_primitive(element.env.get_type_for_declaration_site(element))
def string_encoder_for_type(type_name): if is_primitive(type_name) or type_name == "java.lang.String": return "java_lang_String_valueOf_" + mangle_class_name(type_name) return "java_lang_String_valueOf_java_lang_Object_"
def canonicalize_name(self, simple_name): if is_primitive(simple_name) or simple_name in ["void", "null"]: return simple_name elif simple_name[-2:] == "[]": return self.canonicalize_name(simple_name[:-2]) + "[]" return self.findclass(simple_name).get("canonical_name")
def get_declaration_site_for_name_internal(env, name, type, arglist, canBeClass=True): qualified_parts = name.split(".") if len(qualified_parts) == 1: path = [] if type == "Variable": path += [env.find_nonlocal(name)] if type == "Method": path += [env.find_method_by_name(name, arglist)] path = [x for x in path if x][:1] error_if(not path, "Could not find %s %s" % (type, name)) else: path = [] rhs = None # Initialize for x in range(1, len(qualified_parts) + 1): lhs = ".".join(qualified_parts[:x]) rhs = ".".join(qualified_parts[x:]) if env.find_nonlocal(lhs) is not None: path = [env.find_nonlocal(lhs)] break elif env.find_method_by_name(lhs, arglist) is not None and rhs == "": path = [env.find_method_by_name(lhs, arglist)] break # resolving LHS is a Class elif canBeClass and env.findclass(lhs) is not None: path = [env.findclass(lhs)] break error_if(len(path) == 0, "Cannot find declaration for %s %s" % (type, name)) if isvariable(path[-1]) or (path[-1].tag == "method" and rhs): if isarray(type_string(path[-1])): new_env = env.findclass("java.lang.$Array").env else: if isarray(type_string(path[-1])): new_env = env.findclass("java.lang.$Array").env else: error_if(is_primitive(type_string(path[-1])), "Method called on primitive.") new_env = path[-1].env.findclass( type_string(path[-1])).env else: new_env = path[-1].env path += get_declaration_site_for_name_internal(new_env, rhs, type, arglist, False) return path