aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2011-03-21 15:17:07 +0200
committerHenrik Nord <[email protected]>2011-05-04 15:06:17 +0200
commit5e76fd508af2799fbefe062fd8bb106ae316cf5d (patch)
tree425f4332cef18dcada56e36aaf5e537d5a49d8c7 /lib/dialyzer
parent7a43c9fb7e2a38263132d50dfc5cd922a91f7599 (diff)
downloadotp-5e76fd508af2799fbefe062fd8bb106ae316cf5d.tar.gz
otp-5e76fd508af2799fbefe062fd8bb106ae316cf5d.tar.bz2
otp-5e76fd508af2799fbefe062fd8bb106ae316cf5d.zip
Add opaque/ewgi,ewgi2
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/results/ewgi4
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl240
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl65
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl46
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl241
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl65
-rw-r--r--lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl46
7 files changed, 707 insertions, 0 deletions
diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/ewgi b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi
new file mode 100644
index 0000000000..3c8cfb59f8
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/results/ewgi
@@ -0,0 +1,4 @@
+
+ewgi_api.erl:55: The call gb_trees:to_list({non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument
+ewgi_testapp.erl:35: The call ewgi_testapp:htmlise_data("request_data",{non_neg_integer(),'nil' | {_,_,_,_}}) will never return since it differs in the 2nd argument from the success typing arguments: ([95 | 97 | 100 | 101 | 104 | 112 | 113 | 114 | 115 | 116 | 117,...],[{_,_}])
+ewgi_testapp.erl:43: The call gb_trees:to_list(T::{non_neg_integer(),'nil' | {_,_,_,_}}) does not have an opaque term of type gb_tree() as 1st argument
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
new file mode 100644
index 0000000000..0b98f550f1
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi.hrl
@@ -0,0 +1,240 @@
+-ifndef(_EWGI_HRL).
+-define(_EWGI_HRL, 1).
+
+% ``The contents of this file are subject to the Mozilla Public License
+% Version 1.1 (the "License"); you may not use this file except in
+% compliance with the License. You may obtain a copy of the License at
+% http://www.mozilla.org/MPL/
+%
+% Software distributed under the License is distributed on an "AS IS"
+% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+% License for the specific language governing rights and limitations
+% under the License.
+%
+% The Original Code is the EWGI reference implementation.
+%
+% The Initial Developer of the Original Code is S.G. Consulting
+% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+% 2007 S.G. Consulting srl. All Rights Reserved.
+%
+% Contributor(s): Filippo Pacini <[email protected]>
+% Hunter Morris <[email protected]>
+
+-define(DEFAULT_CHUNKSIZE, 4096).
+
+-type ewgi_propval() :: atom() | integer() | string() | binary().
+-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}.
+-type ewgi_proplist() :: [ewgi_prop()].
+
+%% @type bag() = gb_tree()
+-ifdef(HAS_GB_TREE_SPEC).
+-type bag() :: gb_tree().
+-else.
+-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}.
+-endif.
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()).
+%% @type ewgi_ri_callback() = function()
+-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist().
+
+%% @type ewgi_read_input() = function()
+-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()).
+
+%% @type ewgi_write_error() = function()
+-type ewgi_write_error() :: fun((any()) -> 'ok').
+
+%% @type ewgi_version() = {integer(), integer()}
+-type ewgi_version() :: {integer(), integer()}.
+
+%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(),
+%% ewgi_version(), bag()}
+
+-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(),
+ ewgi_write_error(), string(), ewgi_version(),
+ bag()}.
+
+-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
+ and (size(R) =:= 6))).
+-define(GET_EWGI_READ_INPUT(R), element(2, R)).
+-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
+-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
+-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)).
+-define(GET_EWGI_URL_SCHEME(R), element(4, R)).
+-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)).
+-define(GET_EWGI_VERSION(R), element(5, R)).
+-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)).
+-define(GET_EWGI_DATA(R), element(6, R)).
+-define(SET_EWGI_DATA(A, R), setelement(6, R, A)).
+
+%% @type ewgi_header_val() = string() | 'undefined'
+-type ewgi_header_val() :: string() | 'undefined'.
+
+%% @type ewgi_header_key() = string()
+-type ewgi_header_key() :: string().
+
+%% @type ewgi_http_headers() = {'ewgi_http_headers',
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% bag()}
+
+-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), bag()}.
+
+-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
+ and (size(R) =:= 8))).
+-define(GET_HTTP_ACCEPT(R), element(2, R)).
+-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
+-define(GET_HTTP_COOKIE(R), element(3, R)).
+-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)).
+-define(GET_HTTP_HOST(R), element(4, R)).
+-define(SET_HTTP_HOST(A, R), setelement(4, R, A)).
+-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)).
+-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)).
+-define(GET_HTTP_USER_AGENT(R), element(6, R)).
+-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)).
+-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)).
+-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)).
+-define(GET_HTTP_OTHER(R), element(8, R)).
+-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)).
+
+%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+%% 'DELETE' | 'TRACE' | 'CONNECT' | string()
+-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+ 'DELETE' | 'TRACE' | 'CONNECT' | string().
+
+%% @type ewgi_val() = string() | 'undefined'
+-type ewgi_val() :: string() | 'undefined'.
+
+%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(),
+%% ewgi_spec(), ewgi_val(), ewgi_http_headers(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_request_method(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val()}
+
+-type ewgi_request() :: {'ewgi_request', ewgi_val(),
+ non_neg_integer(), ewgi_val(), ewgi_spec(),
+ ewgi_val(), ewgi_http_headers(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_request_method(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val()}.
+
+-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
+ and (size(R) =:= 21))).
+-define(GET_AUTH_TYPE(R), element(2, R)).
+-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
+-define(GET_CONTENT_LENGTH(R), element(3, R)).
+-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)).
+-define(GET_CONTENT_TYPE(R), element(4, R)).
+-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)).
+-define(GET_EWGI(R), element(5, R)).
+-define(SET_EWGI(A, R), setelement(5, R, A)).
+-define(GET_GATEWAY_INTERFACE(R), element(6, R)).
+-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)).
+-define(GET_HTTP_HEADERS(R), element(7, R)).
+-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)).
+-define(GET_PATH_INFO(R), element(8, R)).
+-define(SET_PATH_INFO(A, R), setelement(8, R, A)).
+-define(GET_PATH_TRANSLATED(R), element(9, R)).
+-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)).
+-define(GET_QUERY_STRING(R), element(10, R)).
+-define(SET_QUERY_STRING(A, R), setelement(10, R, A)).
+-define(GET_REMOTE_ADDR(R), element(11, R)).
+-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)).
+-define(GET_REMOTE_HOST(R), element(12, R)).
+-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)).
+-define(GET_REMOTE_IDENT(R), element(13, R)).
+-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)).
+-define(GET_REMOTE_USER(R), element(14, R)).
+-define(SET_REMOTE_USER(A, R), setelement(14, R, A)).
+-define(GET_REMOTE_USER_DATA(R), element(15, R)).
+-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)).
+-define(GET_REQUEST_METHOD(R), element(16, R)).
+-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)).
+-define(GET_SCRIPT_NAME(R), element(17, R)).
+-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)).
+-define(GET_SERVER_NAME(R), element(18, R)).
+-define(SET_SERVER_NAME(A, R), setelement(18, R, A)).
+-define(GET_SERVER_PORT(R), element(19, R)).
+-define(SET_SERVER_PORT(A, R), setelement(19, R, A)).
+-define(GET_SERVER_PROTOCOL(R), element(20, R)).
+-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)).
+-define(GET_SERVER_SOFTWARE(R), element(21, R)).
+-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)).
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type stream() :: fun(() -> {} | {any(), stream()}).
+%% @type stream() = function()
+-type stream() :: fun(() -> {} | {any(), function()}).
+
+%% @type ewgi_status() = {integer(), string()}
+-type ewgi_status() :: {integer(), string()}.
+
+%% @type ewgi_message_body() = binary() | iolist() | stream()
+-type ewgi_message_body() :: binary() | iolist() | stream().
+
+%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}]
+-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}].
+
+%% @type ewgi_response() = {'ewgi_response', ewgi_status(),
+%% [{ewgi_header_key(), ewgi_header_val()}],
+%% ewgi_message_body(), any()}
+
+-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
+
+-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
+ and (size(R) =:= 5))).
+-define(GET_RESPONSE_STATUS(R), element(2, R)).
+-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
+-define(GET_RESPONSE_HEADERS(R), element(3, R)).
+-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)).
+-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)).
+-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)).
+-define(GET_RESPONSE_ERROR(R), element(5, R)).
+-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)).
+
+%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()}
+
+-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}.
+
+-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
+ and ?IS_EWGI_REQUEST(element(2, R))
+ and ?IS_EWGI_RESPONSE(element(3, R))
+ and (size(R) =:= 3))).
+-define(GET_EWGI_REQUEST(R), element(2, R)).
+-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
+-define(GET_EWGI_RESPONSE(R), element(3, R)).
+-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)).
+
+%% @type ewgi_app() = function()
+-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()).
+
+-ifndef(debug).
+-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx).
+-else.
+-define(INSPECT_EWGI_RESPONSE(Ctx),
+ begin
+ error_logger:info_msg("Inpecting the final ewgi_response()...~n"
+ "Requested Url: ~p~n"
+ "Status: ~p~n"
+ "Headers: ~p~n"
+ "Body: ~p~n",
+ [ewgi_api:path_info(Ctx),
+ ewgi_api:response_status(Ctx),
+ ewgi_api:response_headers(Ctx),
+ ewgi_api:response_message_body(Ctx)]),
+ Ctx
+ end
+ ).
+-endif.
+
+-endif.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl
new file mode 100644
index 0000000000..60da757d3b
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_api.erl
@@ -0,0 +1,65 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_api.erl
+%%% Authors : Filippo Pacini <[email protected]>
+%%% Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and
+%%% limitations under the License.
+%%% The Initial Developer of the Original Code is S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi API. Defines a low level CGI like API.</p>
+%%%
+%%% @end
+%%%
+%%% Created : 10 Oct 2007 by Filippo Pacini <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_api).
+
+-include_lib("ewgi.hrl").
+
+-export([get_all_headers/1, get_all_data/1]).
+
+-spec request(ewgi_context()) -> ewgi_request().
+request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_REQUEST(Ctx).
+
+-spec headers(ewgi_context()) -> ewgi_http_headers().
+headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_HEADERS(request(Ctx)).
+
+get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) ->
+ Hdr = string:to_lower(Hdr0),
+ get_header1(Hdr, Ctx).
+
+get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_ACCEPT(headers(Ctx)).
+
+unzip_header_value([{_,_}|_]=V) ->
+ {_, V1} = lists:unzip(V),
+ string:join(V1, ", ");
+unzip_header_value(V) ->
+ V.
+
+get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ H = headers(Ctx),
+ Other = gb_trees:to_list(?GET_HTTP_OTHER(H)),
+ Acc = [{K, unzip_header_value(V)} || {K, V} <- Other],
+ L = [{"accept", get_header_value("accept", Ctx)}|Acc],
+ lists:filter(fun({_, undefined}) -> false; (_) -> true end, L).
+
+-spec ewgi_spec(ewgi_context()) -> ewgi_spec().
+ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI(request(Ctx)).
+
+get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_DATA(ewgi_spec(Ctx)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl
new file mode 100644
index 0000000000..59c1ae9206
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi/ewgi_testapp.erl
@@ -0,0 +1,46 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_testapp.erl
+%%% Authors : Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and
+%%% limitations under the License.
+%%% The Initial Developer of the Original Code is S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi test applications</p>
+%%%
+%%% @end
+%%%
+%%% Created : 05 July 2009 by Hunter Morris <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_testapp).
+
+-export([htmlise/1]).
+
+-include_lib("ewgi.hrl").
+
+htmlise(C) ->
+ iolist_to_binary(
+ ["<dl class=\"request\">",
+ io_lib:format("<dt>other http headers</dt><dd>~s</dd>", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]),
+ io_lib:format("<dt>ewgi extra data</dt><dd>~s</dd>", [htmlise_data("request_data", ewgi_api:get_all_data(C))]),
+ "</dl>"]).
+
+htmlise_data(Name, L) when is_list(L) ->
+ ["<dl class=\"", Name, "\">",
+ [io_lib:format("<dt>~s</dt><dd><pre>~p</pre><dd>", [K, V]) || {K, V} <- L],
+ "</dl>"];
+htmlise_data(Name, T) ->
+ case gb_trees:to_list(T) of
+ [] -> [];
+ L -> htmlise_data(Name, L)
+ end.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
new file mode 100644
index 0000000000..5da8ff0ecf
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi.hrl
@@ -0,0 +1,241 @@
+-ifndef(_EWGI_HRL).
+-define(_EWGI_HRL, 1).
+
+% ``The contents of this file are subject to the Mozilla Public License
+% Version 1.1 (the "License"); you may not use this file except in
+% compliance with the License. You may obtain a copy of the License at
+% http://www.mozilla.org/MPL/
+%
+% Software distributed under the License is distributed on an "AS IS"
+% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+% License for the specific language governing rights and limitations
+% under the License.
+%
+% The Original Code is the EWGI reference implementation.
+%
+% The Initial Developer of the Original Code is S.G. Consulting
+% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+% 2007 S.G. Consulting srl. All Rights Reserved.
+%
+% Contributor(s): Filippo Pacini <[email protected]>
+% Hunter Morris <[email protected]>
+
+-define(DEFAULT_CHUNKSIZE, 4096).
+-define(HAS_GB_TREE_SPEC, true).
+
+-type ewgi_propval() :: atom() | integer() | string() | binary().
+-type ewgi_prop() :: {ewgi_propval(), ewgi_propval()}.
+-type ewgi_proplist() :: [ewgi_prop()].
+
+%% @type bag() = gb_tree()
+-ifdef(HAS_GB_TREE_SPEC).
+-type bag() :: gb_tree().
+-else.
+-type bag() :: {non_neg_integer(), {any(), any(), any(), any()} | 'nil'}.
+-endif.
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | ewgi_ri_callback()).
+%% @type ewgi_ri_callback() = function()
+-type ewgi_ri_callback() :: fun(('eof' | {data, binary()}) -> iolist() | function()) | iolist().
+
+%% @type ewgi_read_input() = function()
+-type ewgi_read_input() :: fun((ewgi_ri_callback(), integer()) -> ewgi_ri_callback()).
+
+%% @type ewgi_write_error() = function()
+-type ewgi_write_error() :: fun((any()) -> 'ok').
+
+%% @type ewgi_version() = {integer(), integer()}
+-type ewgi_version() :: {integer(), integer()}.
+
+%% @type ewgi_spec() = {'ewgi_spec', function(), function(), string(),
+%% ewgi_version(), bag()}
+
+-type ewgi_spec() :: {'ewgi_spec', ewgi_read_input(),
+ ewgi_write_error(), string(), ewgi_version(),
+ bag()}.
+
+-define(IS_EWGI_SPEC(R), ((element(1, R) =:= 'ewgi_spec')
+ and (size(R) =:= 6))).
+-define(GET_EWGI_READ_INPUT(R), element(2, R)).
+-define(SET_EWGI_READ_INPUT(A, R), setelement(2, R, A)).
+-define(GET_EWGI_WRITE_ERROR(R), element(3, R)).
+-define(SET_EWGI_WRITE_ERROR(A, R), setelement(3, R, A)).
+-define(GET_EWGI_URL_SCHEME(R), element(4, R)).
+-define(SET_EWGI_URL_SCHEME(A, R), setelement(4, R, A)).
+-define(GET_EWGI_VERSION(R), element(5, R)).
+-define(SET_EWGI_VERSION(A, R), setelement(5, R, A)).
+-define(GET_EWGI_DATA(R), element(6, R)).
+-define(SET_EWGI_DATA(A, R), setelement(6, R, A)).
+
+%% @type ewgi_header_val() = string() | 'undefined'
+-type ewgi_header_val() :: string() | 'undefined'.
+
+%% @type ewgi_header_key() = string()
+-type ewgi_header_key() :: string().
+
+%% @type ewgi_http_headers() = {'ewgi_http_headers',
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% ewgi_header_val(),
+%% bag()}
+
+-type ewgi_http_headers() :: {'ewgi_http_headers', ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), ewgi_header_val(),
+ ewgi_header_val(), bag()}.
+
+-define(IS_HTTP_HEADERS(R), ((element(1, R) =:= 'ewgi_http_headers')
+ and (size(R) =:= 8))).
+-define(GET_HTTP_ACCEPT(R), element(2, R)).
+-define(SET_HTTP_ACCEPT(A, R), setelement(2, R, A)).
+-define(GET_HTTP_COOKIE(R), element(3, R)).
+-define(SET_HTTP_COOKIE(A, R), setelement(3, R, A)).
+-define(GET_HTTP_HOST(R), element(4, R)).
+-define(SET_HTTP_HOST(A, R), setelement(4, R, A)).
+-define(GET_HTTP_IF_MODIFIED_SINCE(R), element(5, R)).
+-define(SET_HTTP_IF_MODIFIED_SINCE(A, R), setelement(5, R, A)).
+-define(GET_HTTP_USER_AGENT(R), element(6, R)).
+-define(SET_HTTP_USER_AGENT(A, R), setelement(6, R, A)).
+-define(GET_HTTP_X_HTTP_METHOD_OVERRIDE(R), element(7, R)).
+-define(SET_HTTP_X_HTTP_METHOD_OVERRIDE(A, R), setelement(7, R, A)).
+-define(GET_HTTP_OTHER(R), element(8, R)).
+-define(SET_HTTP_OTHER(A, R), setelement(8, R, A)).
+
+%% @type ewgi_request_method() = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+%% 'DELETE' | 'TRACE' | 'CONNECT' | string()
+-type ewgi_request_method() :: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' |
+ 'DELETE' | 'TRACE' | 'CONNECT' | string().
+
+%% @type ewgi_val() = string() | 'undefined'
+-type ewgi_val() :: string() | 'undefined'.
+
+%% @type ewgi_request() :: {'ewgi_request', ewgi_val(), integer(), ewgi_val(),
+%% ewgi_spec(), ewgi_val(), ewgi_http_headers(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val(), ewgi_val(),
+%% ewgi_request_method(), ewgi_val(), ewgi_val(),
+%% ewgi_val(), ewgi_val(), ewgi_val()}
+
+-type ewgi_request() :: {'ewgi_request', ewgi_val(),
+ non_neg_integer(), ewgi_val(), ewgi_spec(),
+ ewgi_val(), ewgi_http_headers(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_request_method(),
+ ewgi_val(), ewgi_val(), ewgi_val(),
+ ewgi_val(), ewgi_val()}.
+
+-define(IS_EWGI_REQUEST(R), ((element(1, R) =:= 'ewgi_request')
+ and (size(R) =:= 21))).
+-define(GET_AUTH_TYPE(R), element(2, R)).
+-define(SET_AUTH_TYPE(A, R), setelement(2, R, A)).
+-define(GET_CONTENT_LENGTH(R), element(3, R)).
+-define(SET_CONTENT_LENGTH(A, R), setelement(3, R, A)).
+-define(GET_CONTENT_TYPE(R), element(4, R)).
+-define(SET_CONTENT_TYPE(A, R), setelement(4, R, A)).
+-define(GET_EWGI(R), element(5, R)).
+-define(SET_EWGI(A, R), setelement(5, R, A)).
+-define(GET_GATEWAY_INTERFACE(R), element(6, R)).
+-define(SET_GATEWAY_INTERFACE(A, R), setelement(6, R, A)).
+-define(GET_HTTP_HEADERS(R), element(7, R)).
+-define(SET_HTTP_HEADERS(A, R), setelement(7, R, A)).
+-define(GET_PATH_INFO(R), element(8, R)).
+-define(SET_PATH_INFO(A, R), setelement(8, R, A)).
+-define(GET_PATH_TRANSLATED(R), element(9, R)).
+-define(SET_PATH_TRANSLATED(A, R), setelement(9, R, A)).
+-define(GET_QUERY_STRING(R), element(10, R)).
+-define(SET_QUERY_STRING(A, R), setelement(10, R, A)).
+-define(GET_REMOTE_ADDR(R), element(11, R)).
+-define(SET_REMOTE_ADDR(A, R), setelement(11, R, A)).
+-define(GET_REMOTE_HOST(R), element(12, R)).
+-define(SET_REMOTE_HOST(A, R), setelement(12, R, A)).
+-define(GET_REMOTE_IDENT(R), element(13, R)).
+-define(SET_REMOTE_IDENT(A, R), setelement(13, R, A)).
+-define(GET_REMOTE_USER(R), element(14, R)).
+-define(SET_REMOTE_USER(A, R), setelement(14, R, A)).
+-define(GET_REMOTE_USER_DATA(R), element(15, R)).
+-define(SET_REMOTE_USER_DATA(A, R), setelement(15, R, A)).
+-define(GET_REQUEST_METHOD(R), element(16, R)).
+-define(SET_REQUEST_METHOD(A, R), setelement(16, R, A)).
+-define(GET_SCRIPT_NAME(R), element(17, R)).
+-define(SET_SCRIPT_NAME(A, R), setelement(17, R, A)).
+-define(GET_SERVER_NAME(R), element(18, R)).
+-define(SET_SERVER_NAME(A, R), setelement(18, R, A)).
+-define(GET_SERVER_PORT(R), element(19, R)).
+-define(SET_SERVER_PORT(A, R), setelement(19, R, A)).
+-define(GET_SERVER_PROTOCOL(R), element(20, R)).
+-define(SET_SERVER_PROTOCOL(A, R), setelement(20, R, A)).
+-define(GET_SERVER_SOFTWARE(R), element(21, R)).
+-define(SET_SERVER_SOFTWARE(A, R), setelement(21, R, A)).
+
+%%% Note: Dialyzer currently doesn't support recursive types. When it does, this should change:
+%%%-type stream() :: fun(() -> {} | {any(), stream()}).
+%% @type stream() = function()
+-type stream() :: fun(() -> {} | {any(), function()}).
+
+%% @type ewgi_status() = {integer(), string()}
+-type ewgi_status() :: {integer(), string()}.
+
+%% @type ewgi_message_body() = binary() | iolist() | stream()
+-type ewgi_message_body() :: binary() | iolist() | stream().
+
+%% @type ewgi_header_list() = [{ewgi_header_key(), ewgi_header_val()}]
+-type ewgi_header_list() :: [{ewgi_header_key(), ewgi_header_val()}].
+
+%% @type ewgi_response() = {'ewgi_response', ewgi_status(),
+%% [{ewgi_header_key(), ewgi_header_val()}],
+%% ewgi_message_body(), any()}
+
+-type ewgi_response() :: {'ewgi_response', ewgi_status(), ewgi_header_list(), ewgi_message_body(), any()}.
+
+-define(IS_EWGI_RESPONSE(R), ((element(1, R) =:= 'ewgi_response')
+ and (size(R) =:= 5))).
+-define(GET_RESPONSE_STATUS(R), element(2, R)).
+-define(SET_RESPONSE_STATUS(A, R), setelement(2, R, A)).
+-define(GET_RESPONSE_HEADERS(R), element(3, R)).
+-define(SET_RESPONSE_HEADERS(A, R), setelement(3, R, A)).
+-define(GET_RESPONSE_MESSAGE_BODY(R), element(4, R)).
+-define(SET_RESPONSE_MESSAGE_BODY(A, R), setelement(4, R, A)).
+-define(GET_RESPONSE_ERROR(R), element(5, R)).
+-define(SET_RESPONSE_ERROR(A, R), setelement(5, R, A)).
+
+%% @type ewgi_context() = {'ewgi_context', ewgi_request(), ewgi_response()}
+
+-type ewgi_context() :: {'ewgi_context', ewgi_request(), ewgi_response()}.
+
+-define(IS_EWGI_CONTEXT(R), ((element(1, R) =:= 'ewgi_context')
+ and ?IS_EWGI_REQUEST(element(2, R))
+ and ?IS_EWGI_RESPONSE(element(3, R))
+ and (size(R) =:= 3))).
+-define(GET_EWGI_REQUEST(R), element(2, R)).
+-define(SET_EWGI_REQUEST(A, R), setelement(2, R, A)).
+-define(GET_EWGI_RESPONSE(R), element(3, R)).
+-define(SET_EWGI_RESPONSE(A, R), setelement(3, R, A)).
+
+%% @type ewgi_app() = function()
+-type ewgi_app() :: fun((ewgi_context()) -> ewgi_context()).
+
+-ifndef(debug).
+-define(INSPECT_EWGI_RESPONSE(Ctx), Ctx).
+-else.
+-define(INSPECT_EWGI_RESPONSE(Ctx),
+ begin
+ error_logger:info_msg("Inpecting the final ewgi_response()...~n"
+ "Requested Url: ~p~n"
+ "Status: ~p~n"
+ "Headers: ~p~n"
+ "Body: ~p~n",
+ [ewgi_api:path_info(Ctx),
+ ewgi_api:response_status(Ctx),
+ ewgi_api:response_headers(Ctx),
+ ewgi_api:response_message_body(Ctx)]),
+ Ctx
+ end
+ ).
+-endif.
+
+-endif.
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl
new file mode 100644
index 0000000000..60da757d3b
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_api.erl
@@ -0,0 +1,65 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_api.erl
+%%% Authors : Filippo Pacini <[email protected]>
+%%% Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and
+%%% limitations under the License.
+%%% The Initial Developer of the Original Code is S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi API. Defines a low level CGI like API.</p>
+%%%
+%%% @end
+%%%
+%%% Created : 10 Oct 2007 by Filippo Pacini <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_api).
+
+-include_lib("ewgi.hrl").
+
+-export([get_all_headers/1, get_all_data/1]).
+
+-spec request(ewgi_context()) -> ewgi_request().
+request(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_REQUEST(Ctx).
+
+-spec headers(ewgi_context()) -> ewgi_http_headers().
+headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_HEADERS(request(Ctx)).
+
+get_header_value(Hdr0, Ctx) when is_list(Hdr0), ?IS_EWGI_CONTEXT(Ctx) ->
+ Hdr = string:to_lower(Hdr0),
+ get_header1(Hdr, Ctx).
+
+get_header1("accept", Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_HTTP_ACCEPT(headers(Ctx)).
+
+unzip_header_value([{_,_}|_]=V) ->
+ {_, V1} = lists:unzip(V),
+ string:join(V1, ", ");
+unzip_header_value(V) ->
+ V.
+
+get_all_headers(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ H = headers(Ctx),
+ Other = gb_trees:to_list(?GET_HTTP_OTHER(H)),
+ Acc = [{K, unzip_header_value(V)} || {K, V} <- Other],
+ L = [{"accept", get_header_value("accept", Ctx)}|Acc],
+ lists:filter(fun({_, undefined}) -> false; (_) -> true end, L).
+
+-spec ewgi_spec(ewgi_context()) -> ewgi_spec().
+ewgi_spec(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI(request(Ctx)).
+
+get_all_data(Ctx) when ?IS_EWGI_CONTEXT(Ctx) ->
+ ?GET_EWGI_DATA(ewgi_spec(Ctx)).
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl
new file mode 100644
index 0000000000..59c1ae9206
--- /dev/null
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/ewgi2/ewgi_testapp.erl
@@ -0,0 +1,46 @@
+%%%-------------------------------------------------------------------
+%%% File : ewgi_testapp.erl
+%%% Authors : Hunter Morris <[email protected]>
+%%% License :
+%%% The contents of this file are subject to the Mozilla Public
+%%% License Version 1.1 (the "License"); you may not use this file
+%%% except in compliance with the License. You may obtain a copy of
+%%% the License at http://www.mozilla.org/MPL/
+%%%
+%%% Software distributed under the License is distributed on an "AS IS"
+%%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%%% the License for the specific language governing rights and
+%%% limitations under the License.
+%%% The Initial Developer of the Original Code is S.G. Consulting
+%%% srl. Portions created by S.G. Consulting s.r.l. are Copyright (C)
+%%% 2007 S.G. Consulting srl. All Rights Reserved.
+%%%
+%%% @doc
+%%% <p>ewgi test applications</p>
+%%%
+%%% @end
+%%%
+%%% Created : 05 July 2009 by Hunter Morris <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ewgi_testapp).
+
+-export([htmlise/1]).
+
+-include_lib("ewgi.hrl").
+
+htmlise(C) ->
+ iolist_to_binary(
+ ["<dl class=\"request\">",
+ io_lib:format("<dt>other http headers</dt><dd>~s</dd>", [htmlise_data("http_headers", ewgi_api:get_all_headers(C))]),
+ io_lib:format("<dt>ewgi extra data</dt><dd>~s</dd>", [htmlise_data("request_data", ewgi_api:get_all_data(C))]),
+ "</dl>"]).
+
+htmlise_data(Name, L) when is_list(L) ->
+ ["<dl class=\"", Name, "\">",
+ [io_lib:format("<dt>~s</dt><dd><pre>~p</pre><dd>", [K, V]) || {K, V} <- L],
+ "</dl>"];
+htmlise_data(Name, T) ->
+ case gb_trees:to_list(T) of
+ [] -> [];
+ L -> htmlise_data(Name, L)
+ end.