diff options
author | Pascal Rigaux <pixel@mandriva.com> | 2004-01-22 22:17:08 +0000 |
---|---|---|
committer | Pascal Rigaux <pixel@mandriva.com> | 2004-01-22 22:17:08 +0000 |
commit | 811a65122d8248fbbfce20d638c412443c382faa (patch) | |
tree | b710fcc8c0407f9609005344c3a567c26091b36a /perl_checker.src/global_checks.ml | |
parent | e7e339f26bcf34139293fae6db52fa5c45c09647 (diff) | |
download | perl-MDK-Common-811a65122d8248fbbfce20d638c412443c382faa.tar perl-MDK-Common-811a65122d8248fbbfce20d638c412443c382faa.tar.gz perl-MDK-Common-811a65122d8248fbbfce20d638c412443c382faa.tar.bz2 perl-MDK-Common-811a65122d8248fbbfce20d638c412443c382faa.tar.xz perl-MDK-Common-811a65122d8248fbbfce20d638c412443c382faa.zip |
replace the information "a variable is accessed" with the more precise
Access_none | Access_write_only | Access_various
so that we can say either "variable unused" or "variable assigned but not read"
Diffstat (limited to 'perl_checker.src/global_checks.ml')
-rw-r--r-- | perl_checker.src/global_checks.ml | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/perl_checker.src/global_checks.ml b/perl_checker.src/global_checks.ml index 92a0332..b489f6e 100644 --- a/perl_checker.src/global_checks.ml +++ b/perl_checker.src/global_checks.ml @@ -8,15 +8,15 @@ open Tree type state = { per_files : (string, per_file) Hashtbl.t ; per_packages : (string, per_package) Hashtbl.t ; - methods : (string, (pos * bool ref * prototype option) list) Hashtbl.t ; + methods : (string, (pos * variable_used ref * prototype option) list) Hashtbl.t ; global_vars_used : ((context * string * string) * pos) list ref ; packages_being_classes : (string, unit) Hashtbl.t ; } type vars = { - my_vars : ((context * string) * (pos * bool ref * prototype option)) list list ; - our_vars : ((context * string) * (pos * bool ref * prototype option)) list list ; - locally_imported : ((context * string) * (string * bool ref * prototype option)) list ; + my_vars : ((context * string) * (pos * variable_used ref * prototype option)) list list ; + our_vars : ((context * string) * (pos * variable_used ref * prototype option)) list list ; + locally_imported : ((context * string) * (string * variable_used ref * prototype option)) list ; required_vars : (context * string * string) list ; current_package : per_package ; is_toplevel : bool ; @@ -37,7 +37,7 @@ let rec get_imported state current_package (package_name, (imports, pos)) = sndter3 (List.assoc var (get_imports state package_used)) with Not_found -> warn_with_pos pos (sprintf "name %s is not defined in package %s" (variable2s var) package_name) ; - ref true, None + ref Access_various, None in var, (package_name, b, prototype) in @@ -104,13 +104,17 @@ let check_para_comply_with_prototype para proto = let is_anonymous_variable_name s = String.length s > 1 && s.[0] = '_' +let variable_used write_only used = + if !used != Access_various then + used := if write_only then Access_write_only else Access_various + let is_my_declared vars t = List.exists (fun l -> - List.mem_assoc t l && (if not vars.write_only then snd3 (List.assoc t l) := true ; true) + List.mem_assoc t l && (variable_used vars.write_only (snd3 (List.assoc t l)) ; true) ) vars.my_vars let is_our_declared vars t = List.exists (fun l -> - List.mem_assoc t l && (if not vars.write_only then snd3 (List.assoc t l) := true ; true) + List.mem_assoc t l && (variable_used vars.write_only (snd3 (List.assoc t l)) ; true) ) vars.our_vars let is_var_declared_raw write_only state package var para = @@ -126,7 +130,7 @@ let is_var_declared_raw write_only state package var para = with | Some (used, proto) -> check_para_comply_with_prototype para proto ; - if not write_only then used := true ; + variable_used write_only used ; true | None -> false @@ -213,7 +217,7 @@ let declare_My vars (mys, pos) = List.iter (fun v -> if List.mem_assoc v l_pre then warn_with_pos pos (sprintf "redeclared variable %s" (variable2s v)) ) l_new ; - { vars with my_vars = (List.map (fun v -> v, (pos, ref false, None)) l_new @ l_pre) :: List.tl vars.my_vars } + { vars with my_vars = (List.map (fun v -> v, (pos, ref Access_none, None)) l_new @ l_pre) :: List.tl vars.my_vars } let declare_Our vars (ours, pos) = match vars.our_vars with @@ -222,7 +226,7 @@ let declare_Our vars (ours, pos) = List.iter (fun v -> if List.mem_assoc v l_pre && v <> (I_scalar, "_") then warn_with_pos pos (sprintf "redeclared variable %s" (variable2s v)) ) ours ; - { vars with our_vars = (List.map (fun v -> v, (pos, ref false, None)) ours @ l_pre) :: other } + { vars with our_vars = (List.map (fun v -> v, (pos, ref Access_none, None)) ours @ l_pre) :: other } let declare_My_our vars (my_or_our, l, pos) = match my_or_our with @@ -237,13 +241,15 @@ let un_parenthesize_one_elt_List = function let check_unused_local_variables vars = List.iter (fun ((context, s as v), (pos, used, _proto)) -> - if not !used then + if !used != Access_various then match s with | "BEGIN" | "END" | "DESTROY" -> () | "_" when context = I_array -> warn_with_pos pos "if the function doesn't take any parameters, please use the empty prototype.\nexample \"sub foo() { ... }\"" | _ -> - if s.[0] != '_' || s = "_" then warn_with_pos pos (sprintf "unused variable %s" (variable2s v)) + if s.[0] != '_' || s = "_" then + let msg = if !used = Access_write_only then sprintf "variable %s assigned, but not read" else sprintf "unused variable %s" in + warn_with_pos pos (msg (variable2s v)) ) (List.hd vars.my_vars) let check_variables vars t = @@ -256,7 +262,7 @@ let check_variables vars t = Some vars | Call(Deref(I_func, Ident(None, "sort", _)), (Anonymous_sub(_, Block f, pos) :: l)) -> let vars = List.fold_left check_variables_ vars l in - let vars' = { vars with my_vars = [ (I_scalar, "a"), (pos, ref true, None) ; (I_scalar, "b"), (pos, ref true, None) ] :: vars.my_vars ; our_vars = [] :: vars.our_vars } in + let vars' = { vars with my_vars = [ (I_scalar, "a"), (pos, ref Access_various, None) ; (I_scalar, "b"), (pos, ref Access_various, None) ] :: vars.my_vars ; our_vars = [] :: vars.our_vars } in let vars' = List.fold_left check_variables_ vars' f in check_unused_local_variables vars' ; Some vars @@ -264,7 +270,7 @@ let check_variables vars t = | Call(Deref(I_func, Ident(None, func, func_pos)), Anonymous_sub(_, Block f, pos) :: l) when List.mem func [ "grep" ; "map" ; "substInFile" ; "map_index" ; "each_index" ; "partition" ; "find_index" ; "grep_index" ; "find" ; "any" ; "every" ] -> let vars = List.fold_left check_variables_ vars l in - let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref true, None)] :: vars.our_vars } in + let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref Access_various, None)] :: vars.our_vars } in let vars' = List.fold_left check_variables_ vars' f in check_unused_local_variables vars' ; check_variable (I_func, Ident(None, func, func_pos)) vars None ; @@ -299,7 +305,7 @@ let check_variables vars t = | Call_op("while infix", [ expr ; (List [ Call_op("<>", _, _) ] as l) ], pos) | Call_op("for infix", [ expr ; l ], pos) -> let vars = check_variables_ vars l in - let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref true, None)] :: vars.our_vars } in + let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref Access_various, None)] :: vars.our_vars } in let vars' = check_variables_ vars' expr in if List.hd(vars'.my_vars) <> [] then warn_with_pos pos "you can't declare variables in foreach infix"; Some vars @@ -327,11 +333,11 @@ let check_variables vars t = fq = None && List.mem name ["DESTROY"] || Hashtbl.mem vars.state.packages_being_classes (some_or fq vars.current_package.package_name) in - [(I_array, "_"), (pos, ref dont_check_use, None)], body + [(I_array, "_"), (pos, ref (if dont_check_use then Access_various else Access_none), None)], body in let local_vars = if fq = None && name = "AUTOLOAD" - then [ (I_scalar, "AUTOLOAD"), (pos, ref true, None) ] + then [ (I_scalar, "AUTOLOAD"), (pos, ref Access_various, None) ] else [] in let vars' = { vars with my_vars = my_vars :: vars.my_vars ; our_vars = local_vars :: vars.our_vars ; is_toplevel = false } in @@ -340,14 +346,14 @@ let check_variables vars t = Some vars | Anonymous_sub(_, Block l, pos) -> - let vars' = { vars with my_vars = [(I_array, "_"), (pos, ref true, None)] :: vars.my_vars ; is_toplevel = false } in + let vars' = { vars with my_vars = [(I_array, "_"), (pos, ref Access_various, None)] :: vars.my_vars ; is_toplevel = false } in let vars' = List.fold_left check_variables_ vars' l in check_unused_local_variables vars' ; Some vars | Call_op("foreach", [ expr ; Block l ], pos) -> let vars = check_variables_ vars expr in - let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref true, None)] :: vars.our_vars } in + let vars' = { vars with my_vars = [] :: vars.my_vars ; our_vars = [(I_scalar, "_"), (pos, ref Access_various, None)] :: vars.our_vars } in let vars' = List.fold_left check_variables_ vars' l in check_unused_local_variables vars' ; Some vars @@ -442,7 +448,7 @@ let check_variables vars t = l_and | l -> l in - List.iter (fun (used, _) -> used := true) l_and + List.iter (fun (used, _) -> used := Access_various) l_and with Not_found -> if not (List.mem method_ [ "isa"; "can" ]) then warn_with_pos pos ("unknown method " ^ method_)) ; @@ -493,7 +499,7 @@ let add_file_to_files per_files file = let check_unused_vars package = Hashtbl.iter (fun (context, name) (pos, is_used, _proto) -> - if not (!is_used || List.mem name ["BEGIN"; "END"; "DESTROY"; "ISA"; "AUTOLOAD"; "EXPORT"; "EXPORT_OK"; "EXPORT_TAGS"]) then + if not (!is_used != Access_various || List.mem name ["BEGIN"; "END"; "DESTROY"; "ISA"; "AUTOLOAD"; "EXPORT"; "EXPORT_OK"; "EXPORT_TAGS"]) then warn_with_pos pos (sprintf "unused %s%s::%s" (if context = I_func then "function " else "variable " ^ context2s context) package.package_name name) ) package.vars_declared @@ -520,7 +526,7 @@ let arrange_global_vars_declared global_vars_declared state = package in if not (Hashtbl.mem package.vars_declared (context, name)) then - Hashtbl.add package.vars_declared (context, name) (pos, ref false, proto) + Hashtbl.add package.vars_declared (context, name) (pos, ref Access_none, proto) (* otherwise dropping this second declaration *) ) global_vars_declared ; state |