Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'find_this'

Conflicts:
	demos/Makefile
  • Loading branch information...
commit 194b10d06d0cfa860a15a5f7d9c104f749c16487 2 parents 061c6b2 + fec335d
@aryx aryx authored
View
1  .gitignore
@@ -433,3 +433,4 @@ web/old/codemap_client.ml
web/var/logs/access.log
web/var/logs/errors.log
web/var/logs/warnings.log
+/demos/find_methods_return_this
View
19 demos/Makefile
@@ -18,10 +18,10 @@ simple_refactoring: simple_refactoring.ml
../commons/lib.cma ../h_program-lang/lib.cma \
../lang_php/parsing/lib.cma \
simple_refactoring.ml
-
clean::
rm -f simple_refactoring
+# just using $@ and $^ to shorten the command a bit
check_is_static_literal: check_is_static_literal.cmo
ocamlc -g -o $@ \
-I ../commons -I ../lang_php/parsing -I ../h_program-lang \
@@ -29,17 +29,18 @@ check_is_static_literal: check_is_static_literal.cmo
../commons/lib.cma ../h_program-lang/lib.cma \
../lang_php/parsing/lib.cma \
$^
-
clean::
rm -f check_is_static_literal
-find_methods_return_this: find_methods_return_this.cmo
- ocamlc -g -o $@ \
- -I ../commons -I ../lang_php/parsing -I ../h_program-lang \
- str.cma unix.cma nums.cma bigarray.cma \
- ../commons/lib.cma ../h_program-lang/lib.cma \
- ../lang_php/parsing/lib.cma \
- $^
+DEPS1=../commons ../h_program-lang \
+ ../lang_php/parsing ../lang_php/analyze/foundation
+
+INCLUDES1=$(DEPS1:%=-I %)
+CMAS1=$(DEPS1:%=%/lib.cma)
+SYSCMAS1=str.cma unix.cma nums.cma bigarray.cma
+
+find_methods_return_this: find_methods_return_this.ml
+ ocamlc -g -annot -o $@ $(INCLUDES1) $(SYSCMAS1) $(CMAS1) $^
clean::
rm -f find_methods_return_this
View
82 demos/find_methods_return_this.ml
@@ -0,0 +1,82 @@
+open Common (* for +> *)
+
+open Ast_php_simple
+
+let verbose = ref true
+
+let find_methods_return_this_version1 dir =
+ let files = Lib_parsing_php.find_php_files_of_dir_or_files [dir] in
+ files +> Common_extra.progress ~show:!verbose (fun progress_callback ->
+ List.iter (fun file ->
+ progress_callback();
+ let cst = Parse_php.parse_program file in
+ let ast = Ast_php_simple_build.program_with_position_information cst in
+ ast +> List.iter (fun top ->
+ match top with
+ | ClassDef def ->
+ List.iter (fun method_def ->
+ match method_def.f_body with
+ | [] -> ()
+ | xs ->
+ let last = Common.list_last xs in
+ (match last with
+ | Return(_, Some(This(_))) ->
+ pr2 (spf "Found a match in %s %s"
+ file (Ast_php_simple.str_of_name method_def.f_name))
+ | _ -> ()
+ )
+ ) def.c_methods
+ | _ -> ()
+ );
+ )
+ )
+
+open Ast_php
+(* the control flow graph currently works on Ast_php, not Ast_php_simple *)
+module Ast = Ast_php
+module CFG = Controlflow_php
+
+let find_methods_return_this_version2 dir =
+ let files = Lib_parsing_php.find_php_files_of_dir_or_files [dir] in
+ files +> List.iter (fun file ->
+ let cst = Parse_php.parse_program file in
+ let classes = cst +> Common.map_filter (function
+ | ClassDef def -> Some def
+ | _ -> None
+ ) in
+ classes +> List.iter (fun def ->
+ def.c_body +> Ast.unbrace +> List.iter (fun class_stmt ->
+ match class_stmt with
+ | Method def ->
+ let cfg = Controlflow_build_php.cfg_of_func def in
+ let exit_nodei = CFG.find_exit cfg in
+ let pred = cfg#predecessors exit_nodei in
+ let has_only_return_this =
+ pred#tolist +> List.for_all (fun (nodei, _edge) ->
+ let node = cfg#nodes#assoc nodei in
+ match node.CFG.n with
+ | CFG.Return (Some(Lv(This _))) -> true
+ | CFG.Return _ -> false
+ (* when have empty else branch, implicit return void *)
+ | CFG.FalseNode -> false
+ | _ -> false
+
+ )
+ in
+ if has_only_return_this
+ then
+ pr2 (spf "Found a match in %s %s"
+ file (Ast_php.str_of_name def.f_name))
+ | _ -> ()
+ )
+ )
+ )
+
+let main =
+ let func =
+ match Sys.argv.(1) with
+ | "1" -> find_methods_return_this_version1
+ | "2" -> find_methods_return_this_version2
+ | _ -> failwith "usage: find_methods_return_this 1|2 <phpfile>"
+ in
+ func Sys.argv.(2)
View
37 demos/methods_return_this.php
@@ -0,0 +1,37 @@
+<?php
+
+class Foo {
+
+ function ok__simple() {
+ return $this;
+ }
+
+ function ok__last_stmt() {
+ foo();
+ return $this;
+ }
+
+ //TODO
+ function ok__all_branches() {
+ if(true) {
+ return $this;
+ } else {
+ return $this;
+ }
+ }
+
+ //TODO
+ function bad__one_null_branch() {
+ if(false) {
+ return null;
+ }
+ return $this;
+ }
+
+ function bad__one_implicit_null_branch() {
+ if(false) {
+ return $this;
+ }
+ }
+
+}
View
2  lang_php/analyze/checker/error_php.ml
@@ -268,7 +268,7 @@ let rank_errors errs =
| CfgError (Controlflow_build_php.DeadCode node_kind) ->
(match node_kind with
| Controlflow_php.Break -> 3
- | Controlflow_php.Return -> 3
+ | Controlflow_php.Return _ -> 3
| _ -> 15
)
| CfgError _ -> 11
View
2  lang_php/analyze/checker/layer_checker_php.ml
@@ -143,7 +143,7 @@ let info_of_error_and_kind err =
| CfgError (Controlflow_build_php.DeadCode node_kind) ->
(match node_kind with
| Controlflow_php.Break -> "eDeadBreak"
- | Controlflow_php.Return -> "eDeadReturn"
+ | Controlflow_php.Return _ -> "eDeadReturn"
| _ -> "eDeadStatement"
)
| CfgError ( _) ->
View
2  lang_php/analyze/foundation/controlflow_build_php.ml
@@ -303,7 +303,7 @@ let rec (cfg_stmt: state -> nodei option -> stmt -> nodei option) =
)
| Return (t1, eopt, t2) ->
- let newi = state.g#add_node { F.n = F.Return;i=i() } in
+ let newi = state.g#add_node { F.n = F.Return eopt;i=i() } in
state.g +> add_arc_opt (previ, newi);
state.g +> add_arc (newi, state.exiti);
View
14 lang_php/analyze/foundation/controlflow_php.ml
@@ -80,7 +80,8 @@ type node = {
| Case
| Default
(*x: node_kind constructors *)
- | Return
+ | Return of Ast_php.expr option
+
(*x: node_kind constructors *)
| Break
| Continue
@@ -155,7 +156,7 @@ let short_string_of_node_kind nkind =
| IfHeader -> "if(...)"
| Join -> "<join>"
- | Return -> "return ...;"
+ | Return _ -> "return ...;"
| DoHeader -> "do"
| DoWhileTail -> "while(...);"
@@ -184,6 +185,15 @@ let short_string_of_node_kind nkind =
(* Accessors *)
(*****************************************************************************)
+let find_node f cfg =
+ cfg#nodes#tolist +> Common.find_some (fun (nodei, node) ->
+ if f node then Some nodei else None
+ )
+
+let find_exit cfg = find_node (fun node -> node.n = Exit) cfg
+let find_enter cfg = find_node (fun node -> node.n = Enter) cfg
+
+
(*s: controlflow_php accessors *)
let (first_node : flow -> Ograph_extended.nodei) = fun flow ->
raise Todo
View
6 lang_php/analyze/foundation/controlflow_php.mli
@@ -52,7 +52,7 @@ type node = {
| Case
| Default
(*x: node_kind constructors *)
- | Return
+ | Return of Ast_php.expr option
(*x: node_kind constructors *)
| Break
| Continue
@@ -107,6 +107,10 @@ type edge = Direct
type flow = (node, edge) Ograph_extended.ograph_mutable
(*e: type flow *)
+val find_node: (node -> bool) -> flow -> Ograph_extended.nodei
+val find_enter: flow -> Ograph_extended.nodei
+val find_exit: flow -> Ograph_extended.nodei
+
(*s: controlflow helpers signatures *)
val first_node : flow -> Ograph_extended.nodei
val mk_node: node_kind -> node
Please sign in to comment.
Something went wrong with that request. Please try again.