1%% =====================================================================
2%% Licensed under the Apache License, Version 2.0 (the "License"); you may
3%% not use this file except in compliance with the License. You may obtain
4%% a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
5%%
6%% Unless required by applicable law or agreed to in writing, software
7%% distributed under the License is distributed on an "AS IS" BASIS,
8%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9%% See the License for the specific language governing permissions and
10%% limitations under the License.
11%%
12%% Alternatively, you may use this file under the terms of the GNU Lesser
13%% General Public License (the "LGPL") as published by the Free Software
14%% Foundation; either version 2.1, or (at your option) any later version.
15%% If you wish to allow use of your version of this file only under the
16%% terms of the LGPL, you should delete the provisions above and replace
17%% them with the notice and other provisions required by the LGPL; see
18%% <http://www.gnu.org/licenses/>. If you do not delete the provisions
19%% above, a recipient may use your version of this file under the terms of
20%% either the Apache License or the LGPL.
21%%
22%% @copyright 2001-2007 Richard Carlsson
23%% @author Richard Carlsson <carlsson.richard@gmail.com>
24%% @version {@version}
25%% @end
26%% =====================================================================
27
28%% TODO: check weirdness in name generation for @spec f(TypeName, ...) -> ...
29%% TODO: option for ignoring functions matching some pattern ('..._test_'/0)
30%% TODO: @private_type tag, opaque unless generating private docs?
31%% TODO: document the record type syntax
32%% TODO: some 'skip' option for ignoring particular modules?
33%% TODO: multiline comment support (needs modified comment representation)
34%% TODO: config-file for default settings
35%% TODO: config: locations of all local docdirs; generate local doc-index page
36%% TODO: config: URL:s of offline apps
37%% TODO: config: default stylesheet
38%% TODO: config: default header/footer, etc.
39%% TODO: offline linkage
40%% TODO: including source code, explicitly and/or automatically
41
42%% @doc EDoc - the Erlang program documentation generator.
43%%
44%% This module provides the main user interface to EDoc.
45%% <ul>
46%%   <li><a href="overview-summary.html">EDoc User Manual</a></li>
47%%   <li><a href="overview-summary.html#Running_EDoc">Running EDoc</a></li>
48%% </ul>
49
50-module(edoc).
51
52-export([files/1, files/2,
53	 application/1, application/2, application/3,
54	 toc/1, toc/2, toc/3,
55	 run/2,
56	 file/1, file/2,
57	 read/1, read/2,
58	 layout/1, layout/2,
59	 get_doc/1, get_doc/2, get_doc/3,
60	 read_comments/1, read_comments/2,
61	 read_source/1, read_source/2]).
62
63-compile({no_auto_import,[error/1]}).
64
65-include("edoc.hrl").
66
67
68%% @spec (Name::filename()) -> ok
69%% @equiv file(Name, [])
70%% @deprecated See {@link file/2} for details.
71
72file(Name) ->
73    file(Name, []).
74
75%% @spec file(filename(), proplist()) -> ok
76%%
77%% @type filename() = //kernel/file:filename()
78%% @type proplist() = [term()]
79%%
80%% @deprecated This is part of the old interface to EDoc and is mainly
81%% kept for backwards compatibility. The preferred way of generating
82%% documentation is through one of the functions {@link application/2}
83%% and {@link files/2}.
84%%
85%% @doc Reads a source code file and outputs formatted documentation to
86%% a corresponding file.
87%%
88%% Options:
89%% <dl>
90%%  <dt>{@type {dir, filename()@}}
91%%  </dt>
92%%  <dd>Specifies the output directory for the created file. (By
93%%      default, the output is written to the directory of the source
94%%      file.)
95%%  </dd>
96%%  <dt>{@type {source_suffix, string()@}}
97%%  </dt>
98%%  <dd>Specifies the expected suffix of the input file. The default
99%%      value is `".erl"'.
100%%  </dd>
101%%  <dt>{@type {file_suffix, string()@}}
102%%  </dt>
103%%  <dd>Specifies the suffix for the created file. The default value is
104%%      `".html"'.
105%%  </dd>
106%% </dl>
107%%
108%% See {@link get_doc/2} and {@link layout/2} for further
109%% options.
110%%
111%% For running EDoc from a Makefile or similar, see
112%% {@link edoc_run:file/1}.
113%%
114%% @see read/2
115
116%% NEW-OPTIONS: source_suffix, file_suffix, dir
117%% INHERIT-OPTIONS: read/2
118
119file(Name, Options) ->
120    Text = read(Name, Options),
121    SrcSuffix = proplists:get_value(source_suffix, Options,
122				    ?DEFAULT_SOURCE_SUFFIX),
123    BaseName = filename:basename(Name, SrcSuffix),
124    Suffix = proplists:get_value(file_suffix, Options,
125				 ?DEFAULT_FILE_SUFFIX),
126    Dir = proplists:get_value(dir, Options, filename:dirname(Name)),
127    Encoding = [{encoding, edoc_lib:read_encoding(Name, [])}],
128    edoc_lib:write_file(Text, Dir, BaseName ++ Suffix, Encoding).
129
130
131%% TODO: better documentation of files/1/2, application/1/2/3
132
133%% @spec (Files::[filename()]) -> ok
134
135files(Files) ->
136    files(Files, []).
137
138%% @spec (Files::[filename()],
139%%        Options::proplist()) -> ok
140%% @doc Runs EDoc on a given set of source files. See {@link run/2} for
141%% details, including options.
142%% @equiv run([], Files, Options)
143
144files(Files, Options) ->
145    run(Files, Options).
146
147%% @spec (Application::atom()) -> ok
148%% @equiv application(Application, [])
149
150application(App) ->
151    application(App, []).
152
153%% @spec (Application::atom(), Options::proplist()) -> ok
154%% @doc Run EDoc on an application in its default app-directory. See
155%% {@link application/3} for details.
156%% @see application/1
157
158application(App, Options) when is_atom(App) ->
159    case code:lib_dir(App) of
160 	Dir when is_list(Dir) ->
161 	    application(App, Dir, Options);
162 	_ ->
163	    edoc_report:report("cannot find application directory for '~s'.",
164                               [App]),
165 	    exit(error)
166    end.
167
168%% @spec (Application::atom(), Dir::filename(), Options::proplist())
169%%        -> ok
170%% @doc Run EDoc on an application located in the specified directory.
171%% Tries to automatically set up good defaults. Unless the user
172%% specifies otherwise:
173%% <ul>
174%%   <li>The `doc' subdirectory will be used as the target directory, if
175%%   it exists; otherwise the application directory is used.
176%%   </li>
177%%   <li>The source code is assumed to be located in the `src'
178%%   subdirectory, if it exists, or otherwise in the application
179%%   directory itself.
180%%   </li>
181%%   <li>The {@link run/2. `subpackages'} option is turned on. All found
182%%   source files will be processed.
183%%   </li>
184%%   <li>The `include' subdirectory is automatically added to the
185%%   include path. (Only important if {@link read_source/2.
186%%   preprocessing} is turned on.)
187%%   </li>
188%% </ul>
189%%
190%% See {@link run/2} for details, including options.
191%%
192%% @see application/2
193
194application(App, Dir, Options) when is_atom(App) ->
195    Src = edoc_lib:try_subdir(Dir, ?SOURCE_DIR),
196    Overview = filename:join(edoc_lib:try_subdir(Dir, ?EDOC_DIR),
197			     ?OVERVIEW_FILE),
198    Opts = Options ++ [{source_path, [Src]},
199		       subpackages,
200		       {title, io_lib:fwrite("The ~ts application", [App])},
201		       {overview, Overview},
202		       {dir, filename:join(Dir, ?EDOC_DIR)},
203		       {includes, [filename:join(Dir, "include")]}],
204    Opts1 = set_app_default(App, Dir, Opts),
205    %% Recursively document all subpackages of '' - i.e., everything.
206    run([], [{application, App} | Opts1]).
207
208%% Try to set up a default application base URI in a smart way if the
209%% user has not specified it explicitly.
210
211set_app_default(App, Dir0, Opts) ->
212    case proplists:get_value(app_default, Opts) of
213	undefined ->
214	    AppName = atom_to_list(App),
215	    Dir = edoc_lib:simplify_path(filename:absname(Dir0)),
216	    AppDir = case filename:basename(Dir) of
217			 AppName ->
218			     filename:dirname(Dir);
219			 _ ->
220			     ?APP_DEFAULT
221		     end,
222	    [{app_default, AppDir} | Opts];
223	_ ->
224	    Opts
225    end.
226
227opt_defaults() ->
228    [].
229
230opt_negations() ->
231    [{no_preprocess, preprocess},
232     {no_subpackages, subpackages},
233     {no_report_missing_types, report_missing_types}].
234
235%% @spec run(Files::[filename()],
236%%           Options::proplist()) -> ok
237%% @doc Runs EDoc on a given set of source files. Note
238%% that the doclet plugin module has its own particular options; see the
239%% `doclet' option below.
240%%
241%% Also see {@link layout/2} for layout-related options, and
242%% {@link get_doc/2} for options related to reading source
243%% files.
244%%
245%% Options:
246%% <dl>
247%%  <dt>{@type {app_default, string()@}}
248%%  </dt>
249%%  <dd>Specifies the default base URI for unknown applications.
250%%  </dd>
251%%  <dt>{@type {application, App::atom()@}}
252%%  </dt>
253%%  <dd>Specifies that the generated documentation describes the
254%%      application `App'. This mainly affects generated references.
255%%  </dd>
256%%  <dt>{@type {dir, filename()@}}
257%%  </dt>
258%%  <dd>Specifies the target directory for the generated documentation.
259%%  </dd>
260%%  <dt>{@type {doc_path, [string()]@}}
261%%  </dt>
262%%  <dd>Specifies a list of file system paths pointing to directories that
263%%      contain EDoc-generated documentation. All paths for applications
264%%      in the code path are automatically added.
265%%  </dd>
266%%  <dt>{@type {doclet, Module::atom()@}}
267%%  </dt>
268%%  <dd>Specifies a callback module to be used for creating the
269%%      documentation. The module must export a function `run(Cmd, Ctxt)'.
270%%      The default doclet module is {@link edoc_doclet}; see {@link
271%%      edoc_doclet:run/2} for doclet-specific options.
272%%  </dd>
273%%  <dt>{@type {file_suffix, string()@}}
274%%  </dt>
275%%  <dd>Specifies the suffix used for output files. The default value is
276%%      `".html"'. Note that this also affects generated references.
277%%  </dd>
278%%  <dt>{@type {new, boolean()@}}
279%%  </dt>
280%%  <dd>If the value is `true', any existing `edoc-info' file in the
281%%      target directory will be ignored and overwritten. The default
282%%      value is `false'.
283%%  </dd>
284%%  <dt>{@type {source_path, [filename()]@}}
285%%  </dt>
286%%  <dd>Specifies a list of file system paths used to locate the source
287%%      code for packages.
288%%  </dd>
289%%  <dt>{@type {source_suffix, string()@}}
290%%  </dt>
291%%  <dd>Specifies the expected suffix of input files. The default
292%%      value is `".erl"'.
293%%  </dd>
294%%  <dt>{@type {subpackages, boolean()@}}
295%%  </dt>
296%%  <dd>If the value is `true', all subpackages of specified packages
297%%      will also be included in the documentation. The default value is
298%%      `false'. `no_subpackages' is an alias for `{subpackages,
299%%      false}'.
300%%
301%%      Subpackage source files are found by recursively searching
302%%      for source code files in subdirectories of the known source code
303%%      root directories. (Also see the `source_path' option.) Directory
304%%      names must begin with a lowercase letter and contain only
305%%      alphanumeric characters and underscore, or they will be ignored.
306%%      (For example, a subdirectory named `test-files' will not be
307%%      searched.)
308%%  </dd>
309%% </dl>
310%%
311%% @see files/2
312%% @see application/2
313
314%% NEW-OPTIONS: source_path, application
315%% INHERIT-OPTIONS: init_context/1
316%% INHERIT-OPTIONS: expand_sources/2
317%% INHERIT-OPTIONS: target_dir_info/5
318%% INHERIT-OPTIONS: edoc_lib:find_sources/2
319%% INHERIT-OPTIONS: edoc_lib:run_doclet/2
320%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
321
322run(Files, Opts0) ->
323    Opts = expand_opts(Opts0),
324    Ctxt = init_context(Opts),
325    Dir = Ctxt#context.dir,
326    Path = proplists:append_values(source_path, Opts),
327    Ss = sources(Path, Opts),
328    {Ss1, Ms} = expand_sources(expand_files(Files) ++ Ss, Opts),
329    App = proplists:get_value(application, Opts, ?NO_APP),
330    {App1, Ms1} = target_dir_info(Dir, App, Ms, Opts),
331    Ms2 = edoc_lib:unique(lists:sort(Ms1)),
332    Env = edoc_lib:get_doc_env(App1, Ms2, Opts),
333    Ctxt1 = Ctxt#context{env = Env},
334    Cmd = #doclet_gen{sources = Ss1,
335		      app = App1,
336		      modules = Ms2
337		     },
338    F = fun (M) ->
339		M:run(Cmd, Ctxt1)
340	end,
341    edoc_lib:run_doclet(F, Opts).
342
343expand_opts(Opts0) ->
344    proplists:substitute_negations(opt_negations(),
345				   Opts0 ++ opt_defaults()).
346
347%% NEW-OPTIONS: dir
348%% DEFER-OPTIONS: run/2
349
350init_context(Opts) ->
351    #context{dir = proplists:get_value(dir, Opts, ?CURRENT_DIR),
352	     opts = Opts
353	    }.
354
355%% INHERIT-OPTIONS: edoc_lib:find_sources/2
356
357sources(Path, Opts) ->
358	edoc_lib:find_sources(Path, Opts).
359
360%% Expand user-specified sets of files.
361
362expand_files([F | Fs]) ->
363    [{filename:basename(F), filename:dirname(F)} |
364     expand_files(Fs)];
365expand_files([]) ->
366    [].
367
368%% Create the (assumed) full module names. Keep only the first source
369%% for each module, but preserve the order of the list.
370
371%% NEW-OPTIONS: source_suffix
372%% DEFER-OPTIONS: run/2
373
374expand_sources(Ss, Opts) ->
375    Suffix = proplists:get_value(source_suffix, Opts,
376				 ?DEFAULT_SOURCE_SUFFIX),
377    Ss1 = [{F,D} || {F,D} <- Ss],
378    expand_sources(Ss1, Suffix, sets:new(), [], []).
379
380expand_sources([{F, D} | Fs], Suffix, S, As, Ms) ->
381    M = list_to_atom(filename:rootname(F, Suffix)),
382    case sets:is_element(M, S) of
383	true ->
384	    expand_sources(Fs, Suffix, S, As, Ms);
385	false ->
386	    S1 = sets:add_element(M, S),
387	    expand_sources(Fs, Suffix, S1, [{M, F, D} | As],
388			   [M | Ms])
389    end;
390expand_sources([], _Suffix, _S, As, Ms) ->
391    {lists:reverse(As), lists:reverse(Ms)}.
392
393%% NEW-OPTIONS: new
394
395target_dir_info(Dir, App, Ms, Opts) ->
396    case proplists:get_bool(new, Opts) of
397	true ->
398	    {App, Ms};
399	false ->
400	    {App1, Ms1} = edoc_lib:read_info_file(Dir),
401	    {if App == ?NO_APP -> App1;
402		true -> App
403	     end,
404	     Ms ++ Ms1}
405    end.
406
407
408%% @hidden   Not official yet
409
410toc(Dir) ->
411    toc(Dir, []).
412
413%% @equiv toc(Dir, Paths, [])
414%% @hidden   Not official yet
415
416%% NEW-OPTIONS: doc_path
417
418toc(Dir, Opts) ->
419    Paths = proplists:append_values(doc_path, Opts)
420	++ edoc_lib:find_doc_dirs(),
421    toc(Dir, Paths, Opts).
422
423%% @doc Create a meta-level table of contents.
424%% @hidden   Not official yet
425
426%% INHERIT-OPTIONS: init_context/1
427%% INHERIT-OPTIONS: edoc_lib:run_doclet/2
428%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
429
430toc(Dir, Paths, Opts0) ->
431    Opts = expand_opts(Opts0 ++ [{dir, Dir}]),
432    Ctxt = init_context(Opts),
433    Env = edoc_lib:get_doc_env('', [], Opts),
434    Ctxt1 = Ctxt#context{env = Env},
435    F = fun (M) ->
436		M:run(#doclet_toc{paths=Paths}, Ctxt1)
437	end,
438    edoc_lib:run_doclet(F, Opts).
439
440
441%% @spec read(File::filename()) -> string()
442%% @equiv read(File, [])
443
444read(File) ->
445    read(File, []).
446
447%% @spec read(File::filename(), Options::proplist()) -> string()
448%%
449%% @doc Reads and processes a source file and returns the resulting
450%% EDoc-text as a string. See {@link get_doc/2} and {@link layout/2} for
451%% options.
452%%
453%% @see file/2
454
455%% INHERIT-OPTIONS: get_doc/2, layout/2
456
457read(File, Opts) ->
458    {_ModuleName, Doc} = get_doc(File, Opts),
459    layout(Doc, Opts).
460
461
462%% @spec layout(Doc::edoc_module()) -> string()
463%% @equiv layout(Doc, [])
464
465layout(Doc) ->
466    layout(Doc, []).
467
468%% @spec layout(Doc::edoc_module(), Options::proplist()) -> string()
469%%
470%% @doc Transforms EDoc module documentation data to text. The default
471%% layout creates an HTML document.
472%%
473%% Options:
474%% <dl>
475%%  <dt>{@type {layout, Module::atom()@}}
476%%  </dt>
477%%  <dd>Specifies a callback module to be used for formatting. The
478%%      module must export a function `module(Doc, Options)'. The
479%%      default callback module is {@link edoc_layout}; see {@link
480%%      edoc_layout:module/2} for layout-specific options.
481%%  </dd>
482%% </dl>
483%%
484%% @see layout/1
485%% @see run/2
486%% @see read/2
487%% @see file/2
488
489%% INHERIT-OPTIONS: edoc_lib:run_layout/2
490
491layout(Doc, Opts) ->
492    F = fun (M) ->
493		M:module(Doc, Opts)
494	end,
495    edoc_lib:run_layout(F, Opts).
496
497
498%% @spec (File) ->  [comment()]
499%% @type comment() = {Line, Column, Indentation, Text}
500%% where
501%%   Line = integer(),
502%%   Column = integer(),
503%%   Indentation = integer(),
504%%   Text = [string()]
505%% @equiv read_comments(File, [])
506
507read_comments(File) ->
508    read_comments(File, []).
509
510%% @spec read_comments(File::filename(), Options::proplist()) ->
511%%           [comment()]
512%%
513%% @doc Extracts comments from an Erlang source code file. See the
514%% module {@link //syntax_tools/erl_comment_scan} for details on the
515%% representation of comments. Currently, no options are avaliable.
516
517read_comments(File, _Opts) ->
518    erl_comment_scan:file(File).
519
520
521%% @spec (File) -> [syntaxTree()]
522%% @equiv read_source(File, [])
523
524read_source(Name) ->
525    read_source(Name, []).
526
527%% @spec read_source(File::filename(), Options::proplist()) ->
528%%           [syntaxTree()]
529%%
530%% @type syntaxTree() = //syntax_tools/erl_syntax:syntaxTree()
531%%
532%% @doc Reads an Erlang source file and returns the list of "source code
533%% form" syntax trees.
534%%
535%% Options:
536%% <dl>
537%%  <dt>{@type {preprocess, boolean()@}}
538%%  </dt>
539%%  <dd>If the value is `true', the source file will be read via the
540%%      Erlang preprocessor (`epp'). The default value is `false'.
541%%      `no_preprocess' is an alias for `{preprocess, false}'.
542%%
543%%      Normally, preprocessing is not necessary for EDoc to work, but
544%%      if a file contains too exotic definitions or uses of macros, it
545%%      will not be possible to read it without preprocessing. <em>Note:
546%%      comments in included files will not be available to EDoc, even
547%%      with this option enabled.</em>
548%%  </dd>
549%%  <dt>{@type {includes, Path::[string()]@}}
550%%  </dt>
551%%  <dd>Specifies a list of directory names to be searched for include
552%%      files, if the `preprocess' option is turned on. Also used with
553%%      the `@headerfile' tag. The default value is the empty list. The
554%%      directory of the source file is always automatically appended to
555%%      the search path.
556%%  </dd>
557%%  <dt>{@type {macros, [{atom(), term()@}]@}}
558%%  </dt>
559%%  <dd>Specifies a list of pre-defined Erlang preprocessor (`epp')
560%%      macro definitions, used if the `preprocess' option is turned on.
561%%      The default value is the empty list.</dd>
562%%  <dt>{@type {report_missing_types, boolean()@}}
563%%  </dt>
564%%  <dd>If the value is `true', warnings are issued for missing types.
565%%      The default value is `false'.
566%%      `no_report_missing_types' is an alias for
567%%      `{report_missing_types, false}'.
568%%  </dd>
569%% </dl>
570%%
571%% @see get_doc/2
572%% @see //syntax_tools/erl_syntax
573
574%% NEW-OPTIONS: [no_]preprocess (preprocess -> includes, macros)
575
576read_source(Name, Opts0) ->
577    Opts = expand_opts(Opts0),
578    case read_source_1(Name, Opts) of
579	{ok, Forms} ->
580	    check_forms(Forms, Name, Opts),
581	    Forms;
582	{error, R} ->
583	    edoc_report:error({"error reading file '~ts'.",
584                               [edoc_lib:filename(Name)]}),
585	    exit({error, R})
586    end.
587
588read_source_1(Name, Opts) ->
589    case proplists:get_bool(preprocess, Opts) of
590	true ->
591	    read_source_2(Name, Opts);
592	false ->
593	    epp_dodger:quick_parse_file(Name, Opts ++ [{no_fail, false}])
594    end.
595
596read_source_2(Name, Opts) ->
597    Includes = proplists:append_values(includes, Opts)
598	++ [filename:dirname(Name)],
599    Macros = proplists:append_values(macros, Opts),
600    %% epp:parse_file(Name, Includes, Macros).
601    parse_file(Name, Includes, Macros).
602
603%% The code below has been copied from epp.erl.
604%%
605%% Copy the line of the last token to the last token that will be
606%% part of the parse tree.
607%%
608%% The last line is used in edoc_extract:find_type_docs() to determine
609%% if a type declaration is followed by a comment.
610%% <example>
611%%    -type t() :: [
612%%                    {tag, integer()}
613%%                 ].
614%%   %% Protocol options.
615%% </example>
616%% The line of the dot token will be copied to the integer token.
617
618parse_file(Name, Includes, Macros) ->
619    case parse_file(utf8, Name, Includes, Macros) of
620        invalid_unicode ->
621            parse_file(latin1, Name, Includes, Macros);
622        Ret ->
623            Ret
624    end.
625
626parse_file(DefEncoding, Name, Includes, Macros) ->
627    Options = [{name, Name},
628               {includes, Includes},
629               {macros, Macros},
630               {default_encoding, DefEncoding}],
631    case epp:open([extra | Options]) of
632        {ok, Epp, Extra} ->
633            try parse_file(Epp) of
634                Forms ->
635                    Encoding = proplists:get_value(encoding, Extra),
636                    case find_invalid_unicode(Forms) of
637                        invalid_unicode when Encoding =/= utf8 ->
638                            invalid_unicode;
639                        _ ->
640                            {ok, Forms}
641                    end
642            after _ = epp:close(Epp)
643            end;
644        Error ->
645            Error
646    end.
647
648find_invalid_unicode([H|T]) ->
649    case H of
650	{error,{_Line,file_io_server,invalid_unicode}} ->
651	    invalid_unicode;
652	_Other ->
653	    find_invalid_unicode(T)
654    end;
655find_invalid_unicode([]) -> none.
656
657parse_file(Epp) ->
658    case scan_and_parse(Epp) of
659	{ok, Form} ->
660            [Form | parse_file(Epp)];
661	{error, E} ->
662	    [{error, E} | parse_file(Epp)];
663	{eof, Location} ->
664	    [{eof, Location}]
665    end.
666
667scan_and_parse(Epp) ->
668    case epp:scan_erl_form(Epp) of
669        {ok, Toks0} ->
670            Toks = fix_last_line(Toks0),
671            case erl_parse:parse_form(Toks) of
672                {ok, Form} ->
673                    {ok, Form};
674                Else ->
675                    Else
676            end;
677        Else ->
678            Else
679    end.
680
681fix_last_line(Toks0) ->
682    Toks1 = lists:reverse(Toks0),
683    LastLine = erl_scan:line(hd(Toks1)),
684    fll(Toks1, LastLine, []).
685
686fll([{Category, Anno0, Symbol} | L], LastLine, Ts) ->
687    Anno = erl_anno:set_line(LastLine, Anno0),
688    lists:reverse(L, [{Category, Anno, Symbol} | Ts]);
689fll([T | L], LastLine, Ts) ->
690    fll(L, LastLine, [T | Ts]);
691fll(L, _LastLine, Ts) ->
692    lists:reverse(L, Ts).
693
694check_forms(Fs, Name, Opts) ->
695    Fun = fun (F) ->
696	     case erl_syntax:type(F) of
697		 error_marker ->
698		     case erl_syntax:error_marker_info(F) of
699			 {L, M, D} ->
700                             edoc_report:error(L, Name, {format_error, M, D}),
701                             case proplists:get_bool(preprocess, Opts) of
702                                 true ->
703                                     ok;
704                                 false ->
705                                     helpful_message(Name)
706                             end;
707			 Other ->
708			     edoc_report:report(Name, "unknown error in "
709                                                "source code: ~w.", [Other])
710		     end,
711		     exit(error);
712		 _ ->
713		     ok
714	     end
715	  end,
716    lists:foreach(Fun, Fs).
717
718helpful_message(Name) ->
719    Ms = ["If the error is caused by too exotic macro",
720          "definitions or uses of macros, adding option",
721          "{preprocess, true} can help. See also edoc(3)."],
722    lists:foreach(fun(M) -> edoc_report:report(Name, M, []) end, Ms).
723
724%% @spec get_doc(File::filename()) -> {ModuleName, edoc_module()}
725%% @equiv get_doc(File, [])
726
727get_doc(File) ->
728    get_doc(File, []).
729
730%% @spec get_doc(File::filename(), Options::proplist()) ->
731%%           {ModuleName, edoc_module()}
732%%	ModuleName = atom()
733%%
734%% @type edoc_module(). The EDoc documentation data for a module,
735%% expressed as an XML document in {@link //xmerl. XMerL} format. See
736%% the file <a href="edoc.dtd">`edoc.dtd'</a> for details.
737%%
738%% @doc Reads a source code file and extracts EDoc documentation data.
739%% Note that without an environment parameter (see {@link get_doc/3}),
740%% hypertext links may not be correct.
741%%
742%% Options:
743%% <dl>
744%%  <dt>{@type {def, Macros@}}
745%%  </dt>
746%%  <dd><ul>
747%%       <li>`Macros' = {@type Macro | [Macro]}</li>
748%%       <li>`Macro' = {@type {Name::atom(), Text::string()@}}</li>
749%%      </ul>
750%%    Specifies a set of EDoc macro definitions. See
751%%    <a href="overview-summary.html#Macro_expansion">Inline macro expansion</a>
752%%    for details.
753%%  </dd>
754%%  <dt>{@type {hidden, boolean()@}}
755%%  </dt>
756%%  <dd>If the value is `true', documentation of hidden functions will
757%%      also be included. The default value is `false'.
758%%  </dd>
759%%  <dt>{@type {private, boolean()@}}
760%%  </dt>
761%%  <dd>If the value is `true', documentation of private functions will
762%%      also be included. The default value is `false'.
763%%  </dd>
764%%  <dt>{@type {todo, boolean()@}}
765%%  </dt>
766%%  <dd>If the value is `true', To-Do notes written using `@todo' or
767%%  `@TODO' tags will be included in the documentation. The default
768%%  value is `false'.
769%%  </dd>
770%% </dl>
771%%
772%% See {@link read_source/2}, {@link read_comments/2} and {@link
773%% edoc_lib:get_doc_env/3} for further options.
774%%
775%% @see get_doc/3
776%% @see run/2
777%% @see edoc_extract:source/5
778%% @see read/2
779%% @see layout/2
780
781%% INHERIT-OPTIONS: get_doc/3
782%% INHERIT-OPTIONS: edoc_lib:get_doc_env/3
783
784get_doc(File, Opts) ->
785    Env = edoc_lib:get_doc_env(Opts),
786    get_doc(File, Env, Opts).
787
788%% @spec get_doc(File::filename(), Env::edoc_lib:edoc_env(),
789%%        Options::proplist()) -> {ModuleName, edoc_module()}
790%%     ModuleName = atom()
791%%
792%% @doc Like {@link get_doc/2}, but for a given environment
793%% parameter. `Env' is an environment created by {@link
794%% edoc_lib:get_doc_env/3}.
795
796%% INHERIT-OPTIONS: read_source/2, read_comments/2, edoc_extract:source/5
797%% DEFER-OPTIONS: get_doc/2
798
799get_doc(File, Env, Opts) ->
800    edoc_extract:source(File, Env, Opts).
801