Browse Source

added error detection for undefined variables

git-svn-id: http://erlydtl.googlecode.com/svn/trunk@57 a5195066-8e3e-0410-a82a-05b01b1b9875
rsaccon 17 years ago
parent
commit
f54590d273
3 changed files with 64 additions and 42 deletions
  1. 31 22
      src/demo/erlydtl_demo.erl
  2. 1 1
      src/erlydtl/erlydtl_base.erl
  3. 32 19
      src/erlydtl/erlydtl_server.erl

+ 31 - 22
src/demo/erlydtl_demo.erl

@@ -143,7 +143,7 @@ render_all() ->
 %% @end 
 %%--------------------------------------------------------------------
 render("var" = Name) ->
-    render(Name, ".html", [{var1, "foostring1"}, {var2, "foostring2"}]);
+    render(Name, ".html", [{var1, "foostring1"}, {var2, "foostring2"}, {var_not_used, "foostring3"}]);
  
 render("extends" = Name) ->
     render(Name, ".html", [{base_var, "base-barstring"}, {test_var, "test-barstring"}]);
@@ -229,30 +229,39 @@ preset(test_for_records_preset) ->
 
 render2(OutDir, Module, Ext, Arg) ->
     case catch apply(Module, render, [Arg]) of
+        {ok, Val, Warnings} -> 
+            write_file(OutDir, Module, Ext, Val, Warnings);
+        {error, Err, Warnings} ->
+            io:format("TRACE ~p:~p Errors: ~p~n",[?MODULE, ?LINE, Err]),
+            io:format("TRACE ~p:~p Warnings: ~p~n",[?MODULE, ?LINE, Warnings]);
         {'EXIT', Reason} -> 
-            io:format("TRACE ~p:~p ~p: rendering failure: ~n",[?MODULE, ?LINE, Reason]);
-        Val -> 
-            case file:open(filename:join([OutDir, lists:concat([Module, Ext])]), [write]) of
-        		{ok, IoDev} ->
-        		    file:write(IoDev, Val),
-        		    file:close(IoDev),
-        		    io:format("render success: ~p~n",[Module]);        		    
-        		_ ->
-        		    io:format("render failure: ~p~n",[Module])
-        	end
+            io:format("TRACE ~p:~p ~p: render failure: ~n",[?MODULE, ?LINE, Reason])
     end.
     
+    
 render2(OutDir, Module, Ext) ->
-    case catch Module:render() of
+    case catch Module:render() of      
+        {ok, Val, Warnings} -> 
+            write_file(OutDir, Module, Ext, Val, Warnings);
+        {error, Err, Warnings} ->
+            io:format("TRACE ~p:~p Errors: ~p~n",[?MODULE, ?LINE, Err]),
+            io:format("TRACE ~p:~p Warnings: ~p~n",[?MODULE, ?LINE, Warnings]);
         {'EXIT', Reason} -> 
-            io:format("TRACE ~p:~p ~p: rendering failure: ~n",[?MODULE, ?LINE, Reason]);
-        Val -> 
-            case file:open(filename:join([OutDir, lists:concat([Module, Ext])]), [write]) of
-        		{ok, IoDev} ->
-        		    file:write(IoDev, Val),
-        		    file:close(IoDev),
-        		    io:format("render success: ~p~n",[Module]);
-        		_ ->
-        		    io:format("render failure: ~p~n",[Module])
-        	end
+            io:format("TRACE ~p:~p ~p: render failure: ~n",[?MODULE, ?LINE, Reason])
     end.
+
+
+write_file(OutDir, Module, Ext, Val, Warnings) ->
+    case file:open(filename:join([OutDir, lists:concat([Module, Ext])]), [write]) of
+		{ok, IoDev} ->
+		    file:write(IoDev, Val),
+		    file:close(IoDev),
+		    case Warnings of
+		        [] ->
+		            io:format("render success: ~p~n",[Module]);    
+		        _ -> 
+		            io:format("render success: ~p - Warnings: ~p~n",[Module, Warnings])
+		    end;
+		_ ->
+		    io:format("render failure: ~p~n",[Module])
+	end.

+ 1 - 1
src/erlydtl/erlydtl_base.erl

@@ -115,7 +115,7 @@ new_var(List, Acc) ->
 
 binary_string(String) ->
     erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
-    %erl_syntax:string(String).  %% less verbose for debugging        
+    % erl_syntax:string(String).  %% less verbose for debugging    
 
 
 %%====================================================================

+ 32 - 19
src/erlydtl/erlydtl_server.erl

@@ -188,41 +188,54 @@ code_change(_OldVsn, State, _Extra) ->
 %%====================================================================
 %% Internal functions
 %%====================================================================
-compile([H | T], Module, Function, DocRoot, Ext, Vars, Reload) ->
+compile([H | T], Module, FuncName, DocRoot, Ext, Vars, Reload) ->
     case erlydtl_base:build_tree(H, T, DocRoot, Ext, Vars) of
         {regular, Out, Args, _} ->
             Out1 = [erlydtl_base:parse_transform(X) ||  X <- Out],
-            create_module(Out1, Args, Module, Function, Reload);
+            create_module(Out1, Args, Module, FuncName, Reload);
         {inherited, Out, Args, _} ->
-            create_module(Out, Args, Module, Function, Reload);
+            create_module(Out, Args, Module, FuncName, Reload);
         {error, Reason} ->
             {error, Reason}
     end.   
        
-            
-create_module(List, Args, Module, Function, Reload) ->
-    {BodyAST, Args1} = case Args of 
+    
+create_module(List, Args, Module, FuncName, Reload) ->
+    case Args of 
         []  ->
-            {[erl_syntax:list(List)], []};
-        _ ->
+            Body = erl_syntax:tuple([
+                erl_syntax:atom(ok), 
+                erl_syntax:list(List),
+                erl_syntax:list([])]),
+            create_module2([Body], [], Module, FuncName, Reload);
+        _ ->            
+            Warnings = erl_syntax:list([]), %% TODO: add warnings for unused variables
+            Ret = erl_syntax:tuple([erl_syntax:atom(ok), erl_syntax:list(List), Warnings]),
             Var = erl_syntax:variable(erlydtl_base:new_var(Args, 0)),
-            BodyAST0 = lists:foldl(fun(X, Acc) -> 
+            Body = lists:foldl(fun(X, Acc) -> 
                     X2 = list_to_atom(tl(atom_to_list(X))),
                     A = erl_syntax:variable(X),
                     B = erl_syntax:application(erl_syntax:atom(proplists), 
                         erl_syntax:atom(get_value), [erl_syntax:atom(X2), Var]),
-                    [erl_syntax:match_expr(A, B) | Acc]
+                    ClauseOk = erl_syntax:clause([erl_syntax:variable('_')], none, [B]),                 
+                    Err = erlydtl_base:binary_string("{{ undefined }}"), %% TDOD: return list of errors instead of rendereing  "undefined"                     
+                    ClauseErr = erl_syntax:clause([erl_syntax:atom(undefined)], none, [Err]),                 
+                    C = erl_syntax:case_expr(B, [ClauseErr, ClauseOk]),                
+                    D = erl_syntax:match_expr(A, C),
+                    [D | Acc]
                 end,
-                [erl_syntax:list(List)],
-                Args),
-            {BodyAST0, [Var]}
-    end,
-    ClauseAST = erl_syntax:clause(Args1, none, BodyAST),
-    FuncAST = erl_syntax:function(erl_syntax:atom(Function), [ClauseAST]),
-    [ModAST, CmpAST] = [erl_syntax:attribute(erl_syntax:atom(X), [erl_syntax:atom(Y)]) ||
+                [Ret],
+                Args), 
+            create_module2(Body, [Var], Module, FuncName, Reload)
+    end.
+    
+    
+create_module2(Body, Args, Module, FuncName, Reload) ->
+    Clause = erl_syntax:clause(Args, none, Body),
+    Func = erl_syntax:function(erl_syntax:atom(FuncName), [Clause]),
+    [AttrMod, AttrExp] = [erl_syntax:attribute(erl_syntax:atom(X), [erl_syntax:atom(Y)]) ||
         {X, Y} <- [{"module", Module}, {"compile", "export_all"}]],
-    Forms = [erl_syntax:revert(X) || X <- [ModAST, CmpAST, FuncAST]],
-    % io:format("TRACE ~p:~p Forms: ~p~n",[?MODULE, ?LINE, Forms]),
+    Forms = [erl_syntax:revert(X) || X <- [AttrMod, AttrExp, Func]],
     case compile:forms(Forms) of
         {ok, Module1, Bin} ->
             case erlydtl:write_beam(Module1, Bin, "ebin") of