----------------------------------------------------------------------- -- gen-artifacts-docs -- Artifact for documentation -- Copyright (C) 2012, 2015, 2017, 2018, 2019, 2020, 2021 Stephane Carrez -- Written by Stephane Carrez (Stephane.Carrez@gmail.com) -- -- Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. ----------------------------------------------------------------------- with Ada.Containers.Indefinite_Vectors; with Ada.Containers.Indefinite_Hashed_Maps; with Ada.Strings.Hash; with Ada.Text_IO; with Gen.Model.Packages; private with Util.Strings.Maps; -- with Asis; -- with Asis.Text; -- with Asis.Elements; -- with Asis.Exceptions; -- with Asis.Errors; -- with Asis.Implementation; -- with Asis.Elements; -- with Asis.Declarations; -- The Gen.Artifacts.Docs package is an artifact for the generation of -- application documentation. Its purpose is to scan the project source files -- and extract some interesting information for a developer's guide. The artifact -- scans the Ada source files, the XML configuration files, the XHTML files. -- -- The generated documentation is intended to be published on a web site. -- The Google Wiki style is generated by default. -- -- 1/ In the first step, the project files are scanned and the useful -- documentation is extracted. -- -- 2/ In the second step, the documentation is merged and reconciled. Links to -- documentation pages and references are setup and the final pages are generated. -- -- Ada -- --- -- The documentation starts at the first '== TITLE ==' marker and finishes before the -- package specification. -- -- XHTML -- ----- -- Same as Ada. -- -- XML Files -- ---------- -- The documentation is part of the XML and the documentation or description -- tags are extracted. package Gen.Artifacts.Docs is -- Tag marker (same as Java). TAG_CHAR : constant Character := '@'; -- Specific tags recognized when analyzing the documentation. TAG_AUTHOR : constant String := "author"; TAG_TITLE : constant String := "title"; TAG_INCLUDE : constant String := "include"; TAG_INCLUDE_CONFIG : constant String := "include-config"; TAG_INCLUDE_BEAN : constant String := "include-bean"; TAG_INCLUDE_QUERY : constant String := "include-query"; TAG_INCLUDE_PERM : constant String := "include-permission"; TAG_INCLUDE_DOC : constant String := "include-doc"; TAG_SEE : constant String := "see"; Unknown_Tag : exception; type Doc_Format is (DOC_MARKDOWN, DOC_WIKI_GOOGLE); -- ------------------------------ -- Documentation artifact -- ------------------------------ type Artifact is new Gen.Artifacts.Artifact with private; -- Prepare the model after all the configuration files have been read and before -- actually invoking the generation. overriding procedure Prepare (Handler : in out Artifact; Model : in out Gen.Model.Packages.Model_Definition'Class; Project : in out Gen.Model.Projects.Project_Definition'Class; Context : in out Generator'Class); procedure Generate (Handler : in out Artifact; Context : in out Generator'Class); -- Set the output document format to generate. procedure Set_Format (Handler : in out Artifact; Format : in Doc_Format; Footer : in Boolean); -- Load from the file a list of link definitions which can be injected in the generated doc. -- This allows to avoid polluting the Ada code with external links. procedure Read_Links (Handler : in out Artifact; Path : in String); private type Line_Kind is (L_TEXT, L_LIST, L_LIST_ITEM, L_SEE, L_INCLUDE, L_INCLUDE_CONFIG, L_INCLUDE_BEAN, L_INCLUDE_PERMISSION, L_INCLUDE_QUERY, L_INCLUDE_DOC, L_START_CODE, L_END_CODE, L_HEADER_1, L_HEADER_2, L_HEADER_3, L_HEADER_4); subtype Line_Include_Kind is Line_Kind range L_INCLUDE .. L_INCLUDE_DOC; type Line_Type (Len : Natural) is record Kind : Line_Kind := L_TEXT; Content : String (1 .. Len); end record; package Line_Vectors is new Ada.Containers.Indefinite_Vectors (Index_Type => Positive, Element_Type => Line_Type); type Line_Group_Vector is array (Line_Include_Kind) of Line_Vectors.Vector; type Doc_State is (IN_PARA, IN_SEPARATOR, IN_CODE, IN_CODE_SEPARATOR, IN_LIST); type Document_Formatter is abstract tagged record Links : Util.Strings.Maps.Map; end record; type Document_Formatter_Access is access all Document_Formatter'Class; type File_Document is record Name : UString; Title : UString; State : Doc_State := IN_PARA; Line_Number : Natural := 0; Lines : Line_Group_Vector; Was_Included : Boolean := False; Print_Footer : Boolean := True; Formatter : Document_Formatter_Access; end record; -- Get the document name from the file document (ex: .wiki or .md). function Get_Document_Name (Formatter : in Document_Formatter; Document : in File_Document) return String is abstract; -- Start a new document. procedure Start_Document (Formatter : in out Document_Formatter; Document : in File_Document; File : in Ada.Text_IO.File_Type) is abstract; -- Write a line in the target document formatting the line if necessary. procedure Write_Line (Formatter : in out Document_Formatter; File : in Ada.Text_IO.File_Type; Line : in Line_Type) is abstract; -- Finish the document. procedure Finish_Document (Formatter : in out Document_Formatter; Document : in File_Document; File : in Ada.Text_IO.File_Type; Source : in String) is abstract; package Doc_Maps is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => File_Document, Hash => Ada.Strings.Hash, Equivalent_Keys => "="); -- Include the document extract represented by Name into the document Into. -- The included document is marked so that it will not be generated. procedure Include (Docs : in out Doc_Maps.Map; Source : in String; Into : in out File_Document; Name : in String; Mode : in Line_Include_Kind; Position : in Natural); -- Generate the project documentation that was collected in Docs. -- The documentation is merged so that the @include tags are replaced by the matching -- document extracts. procedure Generate (Handler : in out Artifact; Docs : in out Doc_Maps.Map; Dir : in String); -- Returns True if the line indicates a bullet or numbered list. function Is_List (Line : in String) return Boolean; -- Returns True if the line indicates a code sample. function Is_Code (Line : in String) return Boolean; -- Append a raw text line to the document. procedure Append_Line (Doc : in out File_Document; Line : in String); -- Look and analyze the tag defined on the line. procedure Append_Tag (Doc : in out File_Document; Tag : in String); -- Analyse the documentation line and collect the documentation text. procedure Append (Doc : in out File_Document; Line : in String); -- After having collected the documentation, terminate the document by making sure -- the opened elements are closed. procedure Finish (Doc : in out File_Document); -- Set the name associated with the document extract. procedure Set_Name (Doc : in out File_Document; Name : in String); -- Set the title associated with the document extract. procedure Set_Title (Doc : in out File_Document; Title : in String); -- Scan the files in the directory referred to by Path and collect the documentation -- in the Docs hashed map. procedure Scan_Files (Handler : in out Artifact; Path : in String; Docs : in out Doc_Maps.Map); -- Read the Ada specification/body file and collect the useful documentation. -- To keep the implementation simple, we don't use the ASIS packages to scan and extract -- the documentation. We don't need to look at the Ada specification itself. Instead, -- we assume that the Ada source follows some Ada style guidelines. procedure Read_Ada_File (Handler : in out Artifact; File : in String; Result : in out File_Document); procedure Read_Xml_File (Handler : in out Artifact; File : in String; Result : in out File_Document); -- Read some general purpose documentation files. The documentation file -- can be integrated and merged by using the @include-doc tags and it may -- contain various @ tags. procedure Read_Doc_File (Handler : in out Artifact; File : in String; Result : in out File_Document); type Artifact is new Gen.Artifacts.Artifact with record Xslt_Command : UString; Format : Doc_Format := DOC_WIKI_GOOGLE; Print_Footer : Boolean := True; Formatter : Document_Formatter_Access; end record; end Gen.Artifacts.Docs;