def check_path_for_static(self, path): static_context = is_static_context(self.tree) for path_index in xrange(len(path)): path_element = path[path_index] if isvariable(path_element) or is_method(path_element): if not path_index: if path_element.tag in ["field", "method"]: error_if(is_static_context(path_element), "Non-static access to static member.") error_if(statisicity_mismatch(static_context, is_static_context(path_element)), "Direct statisicity mismatch.") elif path_index > 0: previous_element = path[path_index - 1] if is_class(previous_element): error_if(not is_static_context(path_element), "Cannot access non-static from static context.") elif isvariable(previous_element): error_if(is_static_context(path_element), "Cannot access static from non-static context.")
def check_field_initializers(tree): #Check the rules specified in Section 8.3.2.3 of the Java Language #Specification regarding forward references. The initializer of a #non-static field must not use (i.e. read) by simple name (i.e. without an #explicit this) itself or a non-static field declared later in the same #class. #The declaration of a member needs to appear before it is used only if the #member is an instance (respectively static) field of a class or interface #C and all of the following conditions hold: #The usage occurs in an instance (respectively static) variable initializer #of C or in an instance (respectively static) initializer of C. #The usage is not on the left hand side of an assignment. #C is the innermost class or interface enclosing the usage. fields = tree.findall(".//field") for x in xrange(len(fields)): field = fields[x] forward_references = fields[x:] forward_reference_names = [] for forward_reference in forward_references: forward_reference_names.append( name_to_str(forward_reference.find(".//variable"))) potential_elements = set() expression_element = field.find("expression") if expression_element is not None: for child in expression_element.findall(".//name"): child_name = name_to_str(child).split(".")[0] if child_name in forward_reference_names: potential_elements.add(child) valid_references = field.findall(".//left_hand_side/name") valid_references += \ field.findall(".//class_instance_creation_expression/name") for child in valid_references: for subchild in child.getiterator(): potential_elements.discard(subchild) error_if(len(potential_elements), "Forward reference not allowed in initializer.") if static_declaration(field): for name in field.findall(".//name"): if hasattr(child, "declaration") and isvariable(child.declaration): field.env.get_declaration_site_for_variable_name(name_to_str(name),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