├── .github └── workflows │ ├── deploy.yml │ └── maven.yml ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── _config.yml ├── coverage-report-sample.png ├── pom.xml ├── sample-project ├── README.md ├── pom.xml ├── src │ └── main │ │ └── java │ │ └── com │ │ └── manoelcampos │ │ ├── sample1 │ │ ├── Class1.java │ │ ├── Class2.java │ │ ├── SubClass1.java │ │ ├── SubClass2.java │ │ └── UndocumentedClass1.java │ │ └── sample2 │ │ ├── Interface1.java │ │ ├── Interface2.java │ │ └── package-info.java └── target │ └── site │ └── apidocs │ └── javadoc-coverage.html └── src └── main └── java └── com └── manoelcampos └── javadoc └── coverage ├── CoverageDoclet.java ├── Utils.java ├── exporter ├── AbstractDataExporter.java ├── ConsoleExporter.java ├── DataExporter.java └── HtmlExporter.java └── stats ├── ClassDocStats.java ├── ClassMembersDocStats.java ├── ClassesDocStats.java ├── DocStats.java ├── JavaDocsStats.java ├── MembersDocStats.java ├── MethodDocStats.java ├── MethodExceptionsDocStats.java ├── MethodParamsDocStats.java ├── MethodTagsDocStats.java ├── PackagesDocStats.java └── package-info.java /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Publish package to the Maven Central Repository 2 | on: 3 | push: 4 | tags: 5 | - 'v*.*.*' 6 | jobs: 7 | publish: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Set up Maven Central Repository 12 | uses: actions/setup-java@v2 13 | with: 14 | java-version: '8' 15 | distribution: 'adopt' 16 | server-id: ossrh 17 | server-username: MAVEN_USERNAME 18 | server-password: MAVEN_PASSWORD 19 | - id: install-secret-key 20 | name: Install gpg secret key 21 | run: cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import 22 | - name: Publish package 23 | run: mvn --no-transfer-progress -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} --batch-mode -Psonatype deploy 24 | env: 25 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 26 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} 27 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Maven Build 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up JDK 8 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 8 20 | - name: Build with Maven 21 | run: mvn -B package 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.classpath 2 | /.project 3 | /.settings/ 4 | **/.idea/* 5 | *~ 6 | *.iml 7 | target 8 | tmp 9 | out 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright ${startYear}-${currentYear} ${name} 2 | 3 | Licensed under the General Public License Version 3 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | https://www.gnu.org/licenses/gpl-3.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaDoc Coverage Doclet 2 | [![Build Status](https://github.com/manoelcampos/javadoc-coverage/actions/workflows/maven.yml/badge.svg)](https://github.com/manoelcampos/javadoc-coverage/actions/workflows/maven.yml) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/0fef8ada2def4d239931f90a50a3f778)](https://www.codacy.com/app/manoelcampos/javadoc-coverage?utm_source=github.com&utm_medium=referral&utm_content=manoelcampos/javadoc-coverage&utm_campaign=Badge_Grade) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.manoelcampos/javadoc-coverage/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.manoelcampos/javadoc-coverage) [![GPL licensed](https://img.shields.io/badge/license-GPL-blue.svg)](http://www.gnu.org/licenses/gpl-3.0) 3 | 4 | ![](coverage-report-sample.png) 5 | 6 | The Doclet parses java source files and checks the percentage of the Java code covered by JavaDoc documentation, including: 7 | - packages (*Java 9 modules not supported yet*) 8 | - classes, inner classes, interfaces and enums 9 | - class attributes 10 | - methods, parameters, exceptions and return value. 11 | 12 | A sample coverage report is available [here](https://manoelcampos.com/javadoc-coverage/sample-project/target/site/apidocs/javadoc-coverage.html). 13 | 14 | Current IDEs warn about missing JavaDoc tags and documentation, allowing you to individually fix the issues, but you don't get a big the picture. 15 | Similar to code coverage tools, this plugin provides a way to get a summarized overview of your project's documentation coverage. 16 | It provides a [Doclet](http://docs.oracle.com/javase/7/docs/technotes/guides/javadoc/doclet/overview.html) to be used with the JavaDoc Tool to show JavaDoc documentation coverage of your project. 17 | 18 | # Usage 19 | 20 | The easier ways to use the plugin is through Maven or Gradle. You can use the plugin calling the JavaDoc Tool directly from the command line (but this isn't handy and it isn't explained here). 21 | 22 | ## Maven: Using the CoverageDoclet in a regular way 23 | 24 | To generate the regular JavaDoc HTML files and the coverage report, you have to include two `` tags for the `maven-javadoc-plugin` inside your project's `pom.xml` file, as the exemple below: 25 | 26 | ```xml 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-javadoc-plugin 32 | 2.10.4 33 | 34 | 35 | 36 | javadoc-html 37 | package 38 | 39 | javadoc 40 | 41 | 42 | 43 | 44 | 45 | javadoc-coverage 46 | package 47 | 48 | javadoc 49 | 50 | 51 | com.manoelcampos.javadoc.coverage.CoverageDoclet 52 | 53 | com.manoelcampos 54 | javadoc-coverage 55 | 1.1.0 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | ``` 64 | 65 | Now, to generate the regular JavaDocs in HTML and the documentation coverage report, you can execute the `package` goal in Maven, using your IDE or the command line inside your project's root directory: 66 | 67 | ```bash 68 | mvn clean package 69 | ``` 70 | 71 | The JavaDoc coverage report is generated by default as `javadoc-coverage.html` at `target/site/apidocs/`. 72 | 73 | There is a [sample project](sample-project) where you can test the plugin. Just execute the command above inside the project's directory to see the results. 74 | 75 | ## Maven: Using the CoverageDoclet with the maven-site-plugin 76 | If you are generating a maven site and want to include the regular JavaDocs HTML and the JavaDoc Coverage Report into the "Reports" section of the site, the `maven-javadoc-plugin` must be included with slightly different configurations into the `` tag (instead of the `` tag), as the example below: 77 | 78 | ```xml 79 | 80 | 81 | 82 | org.apache.maven.plugins 83 | maven-javadoc-plugin 84 | 2.10.4 85 | 86 | 87 | 88 | javadoc-html 89 | 90 | javadoc 91 | 92 | 93 | 94 | 95 | 96 | javadoc-coverage 97 | 98 | javadoc 99 | 100 | 101 | JavaDoc Coverage 102 | Percentage of the code coverage by JavaDoc documentation. 103 | com.manoelcampos.javadoc.coverage.CoverageDoclet 104 | 105 | com.manoelcampos 106 | javadoc-coverage 107 | 1.1.0 108 | 109 | 110 | javadoc-coverage 111 | 113 | -outputName "index.html" 114 | 115 | 116 | 117 | 118 | 119 | 120 | ``` 121 | 122 | Notice that in this case, the coverage report is being generated into the `target/site/javadoc-coverage` (as defined by the `destDir` tag) with the name of `index.html` (as defined by the `` tag), as required for the maven site. More details of additional parameters is provided in the next section. 123 | 124 | Now, to generate the site you can execute: 125 | 126 | ```bash 127 | mvn clean site 128 | ``` 129 | 130 | The list of project's reports will be included into the `target/site/project-reports.html` file. 131 | 132 | ## Gradle 133 | 134 | To use the Doclet with Gradle, add the following code to your `build.gradle` file. 135 | 136 | ```gradle 137 | configurations { 138 | // Other configuration lines might be in here 139 | javadocCoverage 140 | } 141 | dependencies { 142 | // Your application's other dependencies go here. 143 | javadocCoverage "com.manoelcampos:javadoc-coverage:1.1.0" 144 | } 145 | // This generates the Javadoc coverage report into build/reports/javadoc/javadoc-coverage.html 146 | task javadocCoverageReport(type: Javadoc, dependsOn: javadoc) { 147 | source = sourceSets.main.allJava 148 | destinationDir = reporting.file("javadoc") 149 | options.docletpath = configurations.javadocCoverage.files.asType(List) 150 | options.doclet = "com.manoelcampos.javadoc.coverage.CoverageDoclet" 151 | } 152 | // Optionally you can add the dependsOn here so that when you generate the javadoc 153 | // jar, e.g. if you include the javadocJar in a publishing configuration, the javadoc 154 | // coverage report will be generated automatically. 155 | task javadocJar(type: Jar, dependsOn: javadocCoverageReport) { 156 | classifier "javadoc" 157 | from javadoc.destinationDir 158 | } 159 | ``` 160 | 161 | # Additional Configuration (optional) 162 | 163 | You can define additional configurations for the plugin. 164 | The examples below are presented only for Maven (but the same parameters work for Gradle). 165 | 166 | ## Changing the name of the coverage report file 167 | The CoverageDoclet accepts the command line parameter `-outputName` (`-o` for short) to set the name of the report. The following example shows the code to be added to the `` tag of the `maven-javadoc-plugin`: 168 | ```xml 169 | -outputName "my-project-javadoc-coverage-report.html" 170 | ``` 171 | 172 | ## Excluding packages from the coverage report 173 | You can exclude some packages from the coverage report by adding the code example below into the `` tag of the `maven-javadoc-plugin`. 174 | 175 | ```xml 176 | 177 | com.manoelcampos.javadoc.coverage.CoverageDoclet 178 | 179 | com.manoelcampos 180 | javadoc-coverage 181 | 1.1.0 182 | 183 | 184 | com.manoelcampos.sample2 185 | 186 | ``` 187 | 188 | The example shows how to ignore the package `com.manoelcampos.sample2` from the coverage report. The `` tag accepts a list of packages separated by `:` and also wildcards such as `*`. 189 | For more details, check this [link](https://maven.apache.org/plugins/maven-javadoc-plugin/examples/exclude-package-names.html). 190 | 191 | If you are generating the regular JavaDoc HTML files, you have to include this configuration only where the CoverageDoclet is being used into your pom.xml, unless you want these packages to be excluded from the regular JavaDocs too. 192 | 193 | # Building the Doclet from Sources 194 | 195 | The Doclet is a Java Maven project which can be built directly from any IDE or using the following maven command: 196 | 197 | ```bash 198 | mvn clean install 199 | ``` 200 | 201 | The command builds the Doclet and install it at your local maven repository. 202 | 203 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /coverage-report-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/manoelcampos/javadoc-coverage/abf5e2f425ceb002c92858e01032bb2c17a1836f/coverage-report-sample.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 4.0.0 6 | 7 | com.manoelcampos 8 | javadoc-coverage 9 | jar 10 | 1.2.1 11 | 12 | JavaDoc Coverage Doclet 13 | Doclet to generate coverage reports of JavaDoc documentation. 14 | http://manoelcampos.com 15 | 16 | 2017 17 | 18 | 19 | ${maven.build.timestamp} 20 | yyyy 21 | UTF-8 22 | ${encoding} 23 | ${encoding} 24 | ${encoding} 25 | ${encoding} 26 | 27 | 28 | 29 | Manoel Campos da Silva Filho 30 | http://manoelcampos.com 31 | 32 | 33 | 34 | 35 | GPLv3 36 | https://www.gnu.org/licenses/gpl-3.0 37 | 38 | 39 | 40 | 41 | 42 | Manoel Campos da Silva Filho 43 | manoelcampos@gmail.com 44 | Instituto Federal de Educação Ciência e Tecnologia do Tocantins (IFTO) 45 | http://www.ifto.edu.br 46 | 47 | 48 | 49 | 50 | https://github.com/manoelcampos/javadoc-coverage 51 | scm:git@github.com:manoelcampos/javadoc-coverage.git 52 | scm:git@github.com:manoelcampos/javadoc-coverage.git 53 | 54 | 55 | 56 | http://github.com/manoelcampos/javadoc-coverage/issues 57 | GitHub Issues 58 | 59 | 60 | 61 | 62 | 71 | sonatype 72 | 73 | 74 | 75 | org.apache.maven.plugins 76 | maven-source-plugin 77 | 3.0.1 78 | 79 | 80 | attach-sources 81 | 82 | jar-no-fork 83 | 84 | 85 | 86 | 87 | 88 | 89 | org.apache.maven.plugins 90 | maven-javadoc-plugin 91 | 3.0.0 92 | 93 | 94 | attach-javadocs 95 | 96 | jar 97 | 98 | 99 | 100 | 101 | ${encoding} 102 | false 103 | 104 | 105 | 106 | 110 | 111 | org.apache.maven.plugins 112 | maven-gpg-plugin 113 | 1.6 114 | 115 | 116 | sign-artifacts 117 | verify 118 | 119 | sign 120 | 121 | 122 | 124 | 125 | --pinentry-mode 126 | loopback 127 | 128 | 129 | 130 | 131 | 132 | 133 | 137 | 138 | org.sonatype.plugins 139 | nexus-staging-maven-plugin 140 | 1.6.8 141 | true 142 | 143 | ossrh 144 | https://oss.sonatype.org/ 145 | 147 | false 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 160 | 161 | 162 | ossrh 163 | https://oss.sonatype.org/content/repositories/snapshots 164 | 165 | 166 | ossrh 167 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 168 | 169 | 170 | 171 | 172 | 173 | com.sun.tools 174 | tools 175 | ${java.version} 176 | system 177 | ${java.home}/../lib/tools.jar 178 | 179 | 180 | 181 | 182 | 183 | 184 | org.apache.maven.plugins 185 | maven-compiler-plugin 186 | 3.7.0 187 | 188 | 1.8 189 | 1.8 190 | 191 | 192 | 193 | org.apache.maven.plugins 194 | maven-source-plugin 195 | 3.0.1 196 | 197 | 198 | attach-sources 199 | 200 | jar 201 | 202 | 203 | 204 | 205 | 206 | org.apache.maven.plugins 207 | maven-javadoc-plugin 208 | 3.0.0 209 | 210 | 211 | 212 | javadoc-html 213 | package 214 | 215 | javadoc 216 | 217 | 218 | false 219 | 220 | 221 | 222 | 224 | 225 | javadoc-coverage 226 | package 227 | 228 | javadoc 229 | 230 | 231 | com.manoelcampos.javadoc.coverage.CoverageDoclet 232 | 233 | com.manoelcampos 234 | javadoc-coverage 235 | ${project.version} 236 | 237 | false 238 | 239 | 240 | 241 | 242 | 243 | com.mycila.maven-license-plugin 244 | maven-license-plugin 245 | 1.9.0 246 | 247 |
NOTICE
248 | 249 | SLASHSTAR_STYLE 250 | 251 | 252 | **/*.java 253 | 254 | 255 | **/.*/** 256 | sample-project/** 257 | target/** 258 | src/test/** 259 | src/main/resources/** 260 | 261 | 262 | ${project.inceptionYear} 263 | ${maven.build.timestamp} 264 | Manoel Campos da Silva Filho 265 | 266 | true 267 | true 268 |
269 |
270 | 271 | 272 | com.versioneye 273 | versioneye-maven-plugin 274 | 3.11.4 275 | 276 | manoelcampos 277 | 5968248d368b08001a803892 278 | 279 | 284 | 285 | 286 |
287 |
288 |
289 | -------------------------------------------------------------------------------- /sample-project/README.md: -------------------------------------------------------------------------------- 1 | # Sample Maven Project 2 | 3 | This is a project set up to use the JavaDoc Coverage Maven Plugin. 4 | To parse the JavaDocs inside the Java source files and generate both 5 | the regular HTML files and the documentation coverage report, just 6 | execute the command below. 7 | 8 | ```bash 9 | mvn clean package 10 | ``` -------------------------------------------------------------------------------- /sample-project/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 4.0.0 5 | 6 | com.manoelcampos 7 | javadoc-coverage-sample 8 | jar 9 | 1.2.0 10 | 11 | SampleApp 12 | Just a sample application with silly javadoc comments to be parsed by the JavaDoc Coverage Plugin 13 | 14 | 15 | UTF-8 16 | ${encoding} 17 | ${encoding} 18 | ${encoding} 19 | ${encoding} 20 | 21 | 22 | 23 | 24 | 25 | org.apache.maven.plugins 26 | maven-compiler-plugin 27 | 3.7.0 28 | 29 | 1.8 30 | 1.8 31 | 32 | 33 | 34 | 35 | org.apache.maven.plugins 36 | maven-javadoc-plugin 37 | 3.0.0 38 | 39 | 40 | 41 | javadoc-html 42 | package 43 | 44 | javadoc 45 | 46 | 47 | 48 | 49 | 50 | javadoc-coverage 51 | package 52 | 53 | javadoc 54 | 55 | 56 | com.manoelcampos.javadoc.coverage.CoverageDoclet 57 | 58 | com.manoelcampos 59 | javadoc-coverage 60 | 1.2.0 61 | 62 | false 63 | 64 | 68 | -outputName "relatorio.html" 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample1/Class1.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample1; 2 | 3 | /** 4 | * The Class1. 5 | */ 6 | public class Class1 { 7 | /** 8 | * An enum of continents. 9 | */ 10 | public enum Continent { 11 | /** 12 | * African continent. 13 | */ 14 | AFRICA, 15 | ANTARCTICA, 16 | ASIA, 17 | /** 18 | * European continent. 19 | */ 20 | EUROPE, 21 | OCEANIA 22 | } 23 | 24 | private int field1; 25 | private String field2; 26 | 27 | /** 28 | * The field 3. 29 | */ 30 | private String field3; 31 | 32 | public Class1(){ 33 | } 34 | 35 | /** 36 | * A single parameter constructor. 37 | * @throws RuntimeException when nothing works anymore. 38 | */ 39 | public Class1(int param1) throws RuntimeException { 40 | 41 | } 42 | 43 | /** 44 | * A single parameter constructor. 45 | * @param param1 the param1 46 | * @param param2 the param2 47 | */ 48 | public Class1(int param1, double param2, long param3){ 49 | 50 | } 51 | 52 | /** 53 | * Gets value of field 1. 54 | */ 55 | public int getField1(){ 56 | return 0; 57 | } 58 | 59 | public void setField1(int field1) throws IllegalArgumentException{ 60 | this.field1 = field1; 61 | } 62 | 63 | /** 64 | * Gets value of field 2. 65 | * @return the value of field 2 66 | */ 67 | public int getField2(){ 68 | return 0; 69 | } 70 | 71 | /** 72 | * Gets value of field 3. 73 | * @return the value of field 3 74 | */ 75 | public int getField3(){ 76 | return 0; 77 | } 78 | 79 | /** 80 | * An inner class. 81 | */ 82 | public class InnerClass1{ 83 | 84 | /** 85 | * Gets the inner class value. 86 | */ 87 | public double getValue(){ 88 | return 0.0; 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample1/Class2.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample1; 2 | 3 | /** 4 | * The Class2. 5 | */ 6 | public class Class2 { 7 | 8 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample1/SubClass1.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample1; 2 | 3 | /** 4 | * The SubClass1. 5 | */ 6 | public class SubClass1 extends Class1 { 7 | 8 | @Override 9 | public int getField1(){ 10 | return -1; 11 | } 12 | 13 | /** 14 | * Gets the value of field 2 as a negative number. 15 | * @return 16 | */ 17 | @Override 18 | public int getField2(){ 19 | return -1; 20 | } 21 | 22 | /** 23 | * @return {@inheritDoc} 24 | */ 25 | @Override 26 | public int getField3(){ 27 | return -1; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample1/SubClass2.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample1; 2 | 3 | /** 4 | * The SubClass2. 5 | */ 6 | public class SubClass2 extends Class2 { 7 | 8 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample1/UndocumentedClass1.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample1; 2 | 3 | public class UndocumentedClass1 extends Class1 { 4 | private int field1; 5 | 6 | public UndocumentedClass1(){ 7 | } 8 | 9 | public int getField1(){ return field1; } 10 | public void setField1(int field1){ this.field1 = field1; } 11 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample2/Interface1.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample2; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * The Interface1. 7 | */ 8 | public interface Interface1 { 9 | /** 10 | * The code. 11 | */ 12 | int CODE = 1; 13 | 14 | /** 15 | * Gets the square of a number. 16 | * @param num the number to get the square. 17 | * @return the square of the number. 18 | */ 19 | default int square(int num){ return num*num; } 20 | 21 | /** 22 | * Gets the sum. 23 | */ 24 | default int sum(){ return 0; } 25 | 26 | /** 27 | * Computes some equation. 28 | * @throws IllegalArgumentException when the input parameter is negative. 29 | * The exception is not in fact declared in the method signature. 30 | * Since it's an unchecked exception, that isn't required. 31 | */ 32 | int equation(int input) throws IOException; 33 | 34 | /** 35 | * Divide two numbers 36 | * @throws ArithmeticException when b is zero 37 | */ 38 | int divide(int a, int b); 39 | 40 | 41 | /** 42 | * Computes some equation. 43 | * @throws IllegalArgumentException when input parameters are negative. 44 | * The exception is not in fact declared in the method signature. 45 | * Since it's an unchecked exception, that isn't required. 46 | */ 47 | int equation(int input1, int input2) throws IOException, IndexOutOfBoundsException; 48 | 49 | /** 50 | * Computes some equation. 51 | * @param input1 the first input 52 | * @throws IllegalArgumentException when the input1 is negative 53 | * @throws IndexOutOfBoundsException when there are not historic values 54 | */ 55 | int someMethod1(int input1, int input2) throws IOException, IndexOutOfBoundsException; 56 | 57 | /** 58 | * Computes some equation. 59 | * @throws IllegalArgumentException when the input is negative 60 | * @throws IndexOutOfBoundsException when there are not historic values 61 | */ 62 | double someMethod2(double input) throws IOException, IndexOutOfBoundsException, java.lang.IllegalArgumentException; 63 | 64 | /** 65 | * Computes some equation. 66 | * @throws IllegalArgumentException when the input is negative 67 | * @throws IndexOutOfBoundsException when there are not historic values 68 | */ 69 | long someMethod3(long input) throws IOException, IndexOutOfBoundsException, IllegalArgumentException; 70 | 71 | /** 72 | * Computes some equation. 73 | * @throws IllegalArgumentException when the input is negative 74 | * @throws IndexOutOfBoundsException when trying to access an invalid position 75 | */ 76 | long someMethod4(long input) throws IOException, IndexOutOfBoundsException; 77 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample2/Interface2.java: -------------------------------------------------------------------------------- 1 | package com.manoelcampos.sample2; 2 | 3 | import java.io.IOException; 4 | 5 | /** 6 | * The Interface2. 7 | */ 8 | public interface Interface2 { 9 | /** 10 | * The constant1 11 | */ 12 | int CONSTANT1 = 1; 13 | 14 | int CONSTANT2 = 2; 15 | 16 | /** 17 | * The method1. 18 | * 19 | * @param input1 the first input 20 | * @throws IllegalArgumentException when the input1 is negative 21 | * @throws IndexOutOfBoundsException when there are not historic values 22 | */ 23 | int method1(int input1, int input2) throws IOException, IndexOutOfBoundsException; 24 | 25 | /** 26 | * The method2. 27 | * 28 | * @throws IllegalArgumentException when the input is negative 29 | * @throws IndexOutOfBoundsException when there are not historic values 30 | */ 31 | double method2(double input) throws IOException, IndexOutOfBoundsException, java.lang.IllegalArgumentException; 32 | 33 | /** 34 | * The method3. 35 | * 36 | * @throws IllegalArgumentException when the input is negative 37 | * @throws IndexOutOfBoundsException when there are not historic values 38 | */ 39 | long method3(long input) throws IOException, IndexOutOfBoundsException, IllegalArgumentException; 40 | } -------------------------------------------------------------------------------- /sample-project/src/main/java/com/manoelcampos/sample2/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The package com.manoelcampos.sample2. 3 | */ 4 | package com.manoelcampos.sample2; -------------------------------------------------------------------------------- /sample-project/target/site/apidocs/javadoc-coverage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | JavaDoc Coverage Report 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

JavaDoc Coverage Report

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
Element TypeNamePackageDocumentable MembersUndocumentedDocumentedDocumented Percent
 Classes/Interfaces/Enums91888.89%
     InterfaceInterface2com.manoelcampos.sample22271568.18%
         Fields21150.00%
             Methodmethod173457.14%
                 Params21150.00%
                 Exceptions31266.67%
             Methodmethod263350.00%
                 Params1100.00%
                 Exceptions31266.67%
             Methodmethod363350.00%
                 Params1100.00%
                 Exceptions31266.67%
     InterfaceInterface1com.manoelcampos.sample249153469.39%
         Fields101100.00%
             Methodsquare303100.00%
                 Params101100.00%
             Methodsum21150.00%
             Methodequation53240.00%
                 Params1100.00%
                 Exceptions21150.00%
             Methoddivide53240.00%
                 Params2200.00%
                 Exceptions101100.00%
             Methodequation75228.57%
                 Params2200.00%
                 Exceptions32133.33%
             MethodsomeMethod173457.14%
                 Params21150.00%
                 Exceptions31266.67%
             MethodsomeMethod263350.00%
                 Params1100.00%
                 Exceptions31266.67%
             MethodsomeMethod363350.00%
                 Params1100.00%
                 Exceptions31266.67%
             MethodsomeMethod463350.00%
                 Params1100.00%
                 Exceptions31266.67%
     ClassSubClass1com.manoelcampos.sample182675.00%
             ConstructorSubClass11100.00%
             MethodgetField1202100.00%
             MethodgetField221150.00%
             MethodgetField321150.00%
     ClassClass2com.manoelcampos.sample121150.00%
             ConstructorClass21100.00%
     ClassUndocumentedClass1com.manoelcampos.sample183562.50%
         Fields1100.00%
             ConstructorUndocumentedClass11100.00%
             MethodgetField1202100.00%
             MethodsetField1303100.00%
                 Params1100.00%
     ClassClass1com.manoelcampos.sample12251777.27%
         Fields32133.33%
             ConstructorClass11100.00%
             ConstructorClass131266.67%
                 Params1100.00%
                 Exceptions101100.00%
             ConstructorClass141375.00%
                 Params31266.67%
             MethodgetField121150.00%
             MethodsetField14400.00%
                 Params1100.00%
                 Exceptions1100.00%
             MethodgetField2202100.00%
             MethodgetField3202100.00%
     EnumClass1.Continentcom.manoelcampos.sample1129325.00%
             ConstructorContinent1100.00%
             Methodvalues2200.00%
             MethodvalueOf3300.00%
                 Params1100.00%
     ClassClass1.InnerClass1com.manoelcampos.sample141375.00%
             ConstructorInnerClass11100.00%
             MethodgetValue21150.00%
     ClassSubClass2com.manoelcampos.sample121150.00%
             ConstructorSubClass21100.00%
 Packages21150.00%
     Packagecom.manoelcampos.sample2true100.00%
     Packagecom.manoelcampos.sample1false0.00%
Project Documentation Coverage69.44%
261 |
262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/CoverageDoclet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage; 17 | 18 | import com.manoelcampos.javadoc.coverage.exporter.ConsoleExporter; 19 | import com.manoelcampos.javadoc.coverage.exporter.DataExporter; 20 | import com.manoelcampos.javadoc.coverage.exporter.HtmlExporter; 21 | import com.sun.javadoc.DocErrorReporter; 22 | import com.sun.javadoc.Doclet; 23 | import com.sun.javadoc.LanguageVersion; 24 | import com.sun.javadoc.RootDoc; 25 | import com.sun.tools.doclets.standard.Standard; 26 | 27 | import java.io.*; 28 | 29 | /** 30 | * A {@link Doclet} that computes coverage of JavaDoc documentation. 31 | * It is the entry point for the JavaDoc Tool, which can be executed 32 | * either directly using the JavaDoc command line tool or from maven. 33 | * 34 | *

References: 35 | *

38 | *

39 | * 40 | * @author Manoel Campos da Silva Filho 41 | * @see ConsoleExporter 42 | * @since 1.0.0 43 | */ 44 | public class CoverageDoclet { 45 | /** 46 | * A command line parameter to enable defining the name of the coverage report. 47 | * The first value is the long version of the parameter name and the second 48 | * is the short one. 49 | */ 50 | public static final String OUTPUT_NAME_OPTION[] = {"-outputName", "-o"}; 51 | 52 | /** 53 | * The {@link DataExporter} object to export the coverage report to a file 54 | * in a specific format. 55 | */ 56 | private final DataExporter exporter; 57 | private final RootDoc rootDoc; 58 | 59 | /** 60 | * Starts the actual parsing or JavaDoc documentation and generation of the coverage report. 61 | * This is the entry point for the JavaDoc tool to start the Doclet. 62 | * 63 | * @param rootDoc root element which enables reading JavaDoc documentation 64 | * @return true if the Doclet was started successfully, false otherwise 65 | * @see Doclet#start(RootDoc) 66 | */ 67 | public static boolean start(final RootDoc rootDoc) { 68 | return new CoverageDoclet(rootDoc).render(); 69 | } 70 | 71 | /** 72 | * Instantiate the Doclet which will parse the JavaDocs and generate the coverage report. 73 | * 74 | * @param rootDoc root element which enables reading JavaDoc documentation 75 | */ 76 | public CoverageDoclet(final RootDoc rootDoc) { 77 | this.rootDoc = rootDoc; 78 | this.exporter = new HtmlExporter(this); 79 | } 80 | 81 | /** 82 | * Checks if a given parameter is a valid custom parameter accepted by this doclet. 83 | * @param paramName the name of the parameter to check 84 | * @return true if it's a valid custom parameter, false otherwise 85 | */ 86 | private static boolean isCustomParameter(final String paramName) { 87 | return isParameter(paramName, OUTPUT_NAME_OPTION); 88 | } 89 | 90 | /** 91 | * Checks if the name of a given parameter corresponds to either its long or short form. 92 | * 93 | * @param paramName the name of the parameter to check 94 | * @param validNames the list of accepted names for that parameter 95 | * @return true if the given name corresponds to one of the valid names, false otherwise 96 | */ 97 | private static boolean isParameter(final String paramName, final String[] validNames) { 98 | for (String validName : validNames) { 99 | if (validName.equalsIgnoreCase(paramName)) { 100 | return true; 101 | } 102 | } 103 | 104 | return false; 105 | } 106 | 107 | /** 108 | * Validates command line options. 109 | * 110 | * @param options the array of given options 111 | * @param errorReporter an object that allows printing error messages for invalid options 112 | * @return true if the options are valid, false otherwise 113 | * @see Doclet#validOptions(String[][], DocErrorReporter) 114 | */ 115 | public static boolean validOptions(final String[][] options, final DocErrorReporter errorReporter) { 116 | for (final String[] opt : options) { 117 | if (isCustomParameter(opt[0])) { 118 | return true; 119 | } 120 | } 121 | 122 | return Standard.validOptions(options, errorReporter); 123 | } 124 | 125 | /** 126 | * Gets the number of arguments that a given command line option must contain. 127 | * 128 | * @param option the command line option 129 | * @return the number of arguments required for the given option 130 | * @see Doclet#optionLength(String) 131 | */ 132 | public static int optionLength(final String option) { 133 | /*The custom outputName parameter accepts one argument. 134 | * The name of the param counts as the one argument.*/ 135 | if (isCustomParameter(option)) { 136 | return 2; 137 | } 138 | 139 | return Standard.optionLength(option); 140 | } 141 | 142 | /** 143 | * Gets the values associated to a given command line option. 144 | * 145 | * @param optionNames an array containing the valid names for the command line option to get its associated values. 146 | * This array may include the long and short versions of the option name, 147 | * for instance {@code {-outputName, -o}}. 148 | * @return the values associated to the option, where the 0th element is the option itself; 149 | * or an empty array if the option is invalid. 150 | */ 151 | public String[] getOptionValues(final String[] optionNames) { 152 | for (final String[] optionValues : rootDoc.options()) { 153 | if (isParameter(optionValues[0], optionNames)) { 154 | return optionValues; 155 | } 156 | } 157 | 158 | return new String[]{}; 159 | } 160 | 161 | /** 162 | * Gets the version of the Java Programming Language supported 163 | * by this doclet. 164 | * 165 | * @return the Java language supported version 166 | * @see Doclet#languageVersion() 167 | */ 168 | public static LanguageVersion languageVersion() { 169 | return LanguageVersion.JAVA_1_5; 170 | } 171 | 172 | /** 173 | * Renders the JavaDoc documentation for all elements inside the {@link RootDoc} object 174 | * received by this Doclet. 175 | * 176 | * @return true if the {@link RootDoc} was rendered successfully, false otherwise 177 | */ 178 | private boolean render() { 179 | return exporter.build(); 180 | } 181 | 182 | /** 183 | * Gets the root element which enables reading JavaDoc documentation 184 | * from the Java files given to the JavaDoc tool. 185 | */ 186 | public RootDoc getRootDoc() { 187 | return rootDoc; 188 | } 189 | 190 | /** 191 | * Gets a {@link PrintWriter} used by the {@link #exporter} to write 192 | * the coverage report to. 193 | * 194 | * @param file the file to which the coverage report will be saved to 195 | */ 196 | public PrintWriter getWriter(final File file) throws FileNotFoundException { 197 | return new PrintWriter(new OutputStreamWriter(new FileOutputStream(file))); 198 | } 199 | 200 | /** 201 | * Gets a {@link File} object from a given file name. 202 | * 203 | * @param fileName the name of the file to get a {@link File} object. 204 | * @return the {@link File} object 205 | */ 206 | public File getOutputFile(final String fileName) { 207 | final File dir = new File(getOutputDir()); 208 | if (!dir.exists() && !dir.mkdirs()) { 209 | throw new RuntimeException("The directory '" + getOutputDir() + "' was not created due to unknown reason."); 210 | } 211 | 212 | return new File(dir, fileName); 213 | } 214 | 215 | /** 216 | * Gets the output directory passed as a command line argument to javadoc tool. 217 | * 218 | * @return the output directory to export the JavaDocs 219 | */ 220 | private String getOutputDir() { 221 | for (final String[] option : rootDoc.options()) { 222 | if (option.length == 2 && option[0].equals("-d")) { 223 | return Utils.includeTrailingDirSeparator(option[1]); 224 | } 225 | } 226 | 227 | return ""; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage; 17 | 18 | import java.io.File; 19 | import java.util.Arrays; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | import java.util.stream.DoubleStream; 23 | 24 | /** 25 | * Provides some utility methods. 26 | * 27 | * @author Manoel Campos da Silva Filho 28 | * @since 1.0.0 29 | */ 30 | public final class Utils { 31 | /** 32 | * A private constructor to avoid class instantiation. 33 | */ 34 | private Utils() {} 35 | 36 | /** 37 | * Checks if an element (package, class, interface, method or constructor) is in fact documented or not. 38 | * Sometimes, there is a javadoc, but the description of the member is empty. 39 | * The javadoc may just contain tags documenting the elements belonging to this member 40 | * (such as method parameters), but the member itself is not documented. 41 | * 42 | *

WARNING: This method is not useful to check if a {@code @param}, {@code @return} or {@code @throws} tag 43 | * for a method is documented or not.

44 | * 45 | * @param javadoc the complete JavaDoc for an element. 46 | * @return 47 | */ 48 | public static boolean isElementDocumented(final String javadoc) { 49 | /* 50 | * Try to get the text before the first @. This text represents 51 | * the documentation for the element (such as a method). 52 | * The first @ represents the beginning of the first tag (such as a @param tag). 53 | */ 54 | final Matcher matcher = Pattern.compile("^([^@]+)").matcher(javadoc); 55 | return matcher.find() && isNotStringEmpty(matcher.group(0)); 56 | 57 | } 58 | 59 | public static boolean isNotStringEmpty(final String str) { 60 | return !isStringEmpty(str); 61 | } 62 | 63 | public static boolean isStringEmpty(final String str) { 64 | return str == null || str.trim().isEmpty(); 65 | } 66 | 67 | /** 68 | * Adds a trailing slash at the end of a path if it doesn't have one yet. 69 | * The trailing slash type is system-dependent and will be accordingly selected. 70 | * 71 | * @param path the path to include a trailing slash 72 | * @return the path with a trailing slash if there wasn't one and the path is not empty, 73 | * the original path otherwise 74 | */ 75 | public static String includeTrailingDirSeparator(final String path) { 76 | if (path.trim().isEmpty()) { 77 | return path; 78 | } 79 | 80 | if (path.charAt(path.length() - 1) != File.separatorChar) { 81 | return path + File.separator; 82 | } 83 | 84 | return path; 85 | } 86 | 87 | /** 88 | * Computes the percentage that a partial value corresponds to a given total. 89 | * 90 | * @param partialValue the partial value to compute the percentage related to the total value 91 | * @param totalValue the total the partial value corresponds to 92 | * @return the percentage (in scale from 0 to 100) the partial value represents from the total 93 | */ 94 | public static double computePercentage(final double partialValue, final double totalValue){ 95 | if(totalValue == 0){ 96 | return 0; 97 | } 98 | 99 | return (partialValue/totalValue) * 100.0; 100 | 101 | } 102 | 103 | /** 104 | * Computes the mean value from an array. 105 | * 106 | * @param values the values to compute the mean from 107 | * @return the computed mean 108 | */ 109 | public static double mean(final double... values){ 110 | if(values == null){ 111 | return 0; 112 | } 113 | 114 | return mean(Arrays.stream(values)); 115 | } 116 | 117 | /** 118 | * Computes the mean value from a Stream of values. 119 | * 120 | * @param stream the Stream of values to compute the mean from 121 | * @return the computed mean 122 | */ 123 | private static double mean(final DoubleStream stream) { 124 | return stream.average().orElse(0); 125 | } 126 | 127 | /** 128 | * Converts a boolean to its corresponding int 129 | * 130 | * @param bool the boolean value to convert 131 | * @return 1 whether the bool is equal to true; 0 otherwise 132 | */ 133 | public static int boolToInt(final boolean bool) { 134 | return bool ? 1 : 0; 135 | } 136 | 137 | /** 138 | * Gets the extension of a file. 139 | * 140 | * @param fileName the name of the file 141 | * @return the file extension, including the dot, or an empty string 142 | * if there isn't a extension 143 | */ 144 | public static String getFileExtension(final String fileName) { 145 | final int i = fileName.lastIndexOf('.'); 146 | return i > 0 ? fileName.substring(i) : ""; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/exporter/AbstractDataExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.exporter; 17 | 18 | import com.manoelcampos.javadoc.coverage.CoverageDoclet; 19 | import com.manoelcampos.javadoc.coverage.Utils; 20 | import com.manoelcampos.javadoc.coverage.stats.JavaDocsStats; 21 | 22 | import java.io.File; 23 | import java.io.FileNotFoundException; 24 | import java.io.PrintWriter; 25 | 26 | /** 27 | * Abstract class to implement JavaDoc Coverage reports in different formats. 28 | * Each sub-class should implement a specific format such as HTML, CSV, JSON, etc. 29 | * 30 | * @author Manoel Campos da Silva Filho 31 | * @since 1.0.0 32 | */ 33 | public abstract class AbstractDataExporter implements DataExporter { 34 | private final JavaDocsStats stats; 35 | private final PrintWriter writer; 36 | private File file; 37 | private final CoverageDoclet doclet; 38 | private final String reportFileName; 39 | 40 | /** 41 | * Instantiates a DataExporter object to generate JavaDoc coverage report. 42 | * 43 | * @param doclet the {@link CoverageDoclet} which computes teh JavaDoc coverage statistics. 44 | * @param fileExtension the extension to the report file. If empty, the report will be printed to the standard output. 45 | */ 46 | protected AbstractDataExporter(final CoverageDoclet doclet, final String fileExtension) { 47 | this.doclet = doclet; 48 | 49 | if (Utils.isStringEmpty(fileExtension)) { 50 | writer = new PrintWriter(System.out); 51 | this.reportFileName = ""; 52 | } else { 53 | this.reportFileName = generateReportFileName(fileExtension); 54 | try { 55 | this.writer = doclet.getWriter(file); 56 | } catch (FileNotFoundException e) { 57 | throw new RuntimeException(e); 58 | } 59 | } 60 | 61 | this.stats = new JavaDocsStats(doclet.getRootDoc()); 62 | } 63 | 64 | /** 65 | * Instantiates a DataExporter object that generates JavaDoc coverage report to the standard output. 66 | * 67 | * @param doclet the {@link CoverageDoclet} which computes teh JavaDoc coverage statistics. 68 | */ 69 | protected AbstractDataExporter(final CoverageDoclet doclet) { 70 | this(doclet, ""); 71 | } 72 | 73 | private String generateReportFileName(final String fileExtension) { 74 | String fileName = getFileNameFromCommandLine(); 75 | fileName = fileName + fileExtensionToAdd(fileName, fileExtension); 76 | this.file = doclet.getOutputFile(fileName); 77 | return fileName; 78 | } 79 | 80 | /** 81 | * Gets the JavaDoc Coverage Report file name from command line options 82 | * or the default name if no option is given. 83 | * 84 | * @return 85 | * @see CoverageDoclet#OUTPUT_NAME_OPTION 86 | */ 87 | private String getFileNameFromCommandLine() { 88 | final String[] outputNameOption = doclet.getOptionValues(CoverageDoclet.OUTPUT_NAME_OPTION); 89 | return outputNameOption.length > 1 ? outputNameOption[1] : DEFAULT_OUTPUT_NAME; 90 | } 91 | 92 | /** 93 | * Gets the extension to add to a given file if it doesn't have one. 94 | * 95 | * @param fileName the file name to try getting and extension to add 96 | * @param defaultFileExtension the default file extension to return if the file doesn't have one 97 | * @return the file extension to add to the file it it doesn't have one or an empty string 98 | * if it already has. 99 | */ 100 | private String fileExtensionToAdd(final String fileName, final String defaultFileExtension) { 101 | return Utils.getFileExtension(fileName).isEmpty() ? 102 | getFileExtensionStartingWithDot(defaultFileExtension) : ""; 103 | } 104 | 105 | /** 106 | * Adds a dot to the beginning of a file extension if it doesn't have one. 107 | * 108 | * @param fileExtension the file extension 109 | * @return the validated file extension 110 | */ 111 | private String getFileExtensionStartingWithDot(String fileExtension) { 112 | return fileExtension.startsWith(".") ? fileExtension : "." + fileExtension; 113 | } 114 | 115 | @Override 116 | public String getReportFileName() { 117 | return this.reportFileName; 118 | } 119 | 120 | @Override 121 | public boolean build() { 122 | try { 123 | header(); 124 | exportClassesDocStats(); 125 | exportPackagesDocStats(); 126 | exportProjectDocumentationCoverageSummary(); 127 | footer(); 128 | afterBuild(); 129 | getWriter().flush(); 130 | return true; 131 | } finally { 132 | getWriter().close(); 133 | } 134 | } 135 | 136 | protected PrintWriter getWriter() { 137 | return writer; 138 | } 139 | 140 | protected JavaDocsStats getStats() { 141 | return stats; 142 | } 143 | 144 | public File getFile() { 145 | return file; 146 | } 147 | 148 | protected abstract void exportProjectDocumentationCoverageSummary(); 149 | 150 | protected abstract void header(); 151 | 152 | protected abstract void footer(); 153 | 154 | protected abstract void afterBuild(); 155 | 156 | protected abstract void exportPackagesDocStats(); 157 | 158 | protected abstract void exportClassesDocStats(); 159 | } 160 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/exporter/ConsoleExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.exporter; 17 | 18 | import com.manoelcampos.javadoc.coverage.CoverageDoclet; 19 | import com.manoelcampos.javadoc.coverage.Utils; 20 | import com.manoelcampos.javadoc.coverage.stats.*; 21 | import com.sun.javadoc.PackageDoc; 22 | 23 | import java.io.PrintWriter; 24 | import java.util.List; 25 | 26 | /** 27 | * Prints the JavaDoc coverage report to the console (standard output). 28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public class ConsoleExporter extends AbstractDataExporter { 33 | 34 | public ConsoleExporter(final CoverageDoclet doclet) { 35 | super(doclet); 36 | } 37 | 38 | @Override 39 | protected void header() {/**/} 40 | 41 | @Override 42 | protected void footer() {/**/} 43 | 44 | @Override 45 | public void afterBuild() {/**/} 46 | 47 | @Override 48 | protected void exportProjectDocumentationCoverageSummary() { 49 | getWriter().printf("Project Documentation Coverage: %.2f%%\n\n", getStats().getDocumentedMembersPercent()); 50 | } 51 | 52 | @Override 53 | protected void exportPackagesDocStats() { 54 | final PackagesDocStats packagesDocStats = getStats().getPackagesDocStats(); 55 | exportPkgsOrClassesDocStats(packagesDocStats); 56 | packagesDocStats.getPackagesDoc().forEach(this::exportPackageDocStats); 57 | getWriter().println(); 58 | } 59 | 60 | private void exportPkgsOrClassesDocStats(MembersDocStats packagesDocStats) { 61 | getWriter().printf("%-26s: \t%11d Undocumented: %6d Documented: %6d (%.2f%%)\n", 62 | packagesDocStats.getType(), packagesDocStats.getMembersNumber(), packagesDocStats.getUndocumentedMembers(), 63 | packagesDocStats.getDocumentedMembers(), packagesDocStats.getDocumentedMembersPercent()); 64 | } 65 | 66 | /** 67 | * Exports the statistics about JavaDoc coverage of a given package. 68 | * @param doc the object containing the JavaDoc coverage data 69 | * 70 | */ 71 | private void exportPackageDocStats(final PackageDoc doc) { 72 | getWriter().printf("\tPackage %s. Documented: %s\n", doc.name(), Utils.isNotStringEmpty(doc.commentText())); 73 | } 74 | 75 | @Override 76 | protected void exportClassesDocStats() { 77 | final ClassesDocStats classesDocStats = getStats().getClassesDocStats(); 78 | exportPkgsOrClassesDocStats(classesDocStats); 79 | 80 | for (final ClassDocStats classStats : getStats().getClassesDocStats().getClassesList()) { 81 | exportClassDocStats(classStats); 82 | } 83 | getWriter().println(); 84 | } 85 | 86 | /** 87 | * Exports the statistics about JavaDoc coverage of a given class. 88 | * @param classStats the object containing the JavaDoc coverage data 89 | * 90 | */ 91 | private void exportClassDocStats(final ClassDocStats classStats) { 92 | getWriter().printf("\t%s: %s Package: %s Documented: %s (%.2f%%)\n", 93 | classStats.getType(), classStats.getName(), classStats.getPackageName(), 94 | classStats.isDocumented(), classStats.getDocumentedMembersPercent()); 95 | 96 | exportMembersDocStats(getWriter(), classStats.getFieldsStats()); 97 | exportMethodsDocStats(getWriter(), classStats.getConstructorsStats()); 98 | exportMethodsDocStats(getWriter(), classStats.getMethodsStats()); 99 | exportMembersDocStats(getWriter(), classStats.getEnumsStats()); 100 | getWriter().flush(); 101 | } 102 | 103 | private void exportMethodsDocStats(final PrintWriter writer, final List methodStatsList) { 104 | final String memberTypeFormat = "\t\t\t%-12s"; 105 | for (final MethodDocStats methodStats : methodStatsList) { 106 | writer.printf("\t\t%s: %s Documented: %s (%.2f%%)\n", 107 | methodStats.getType(), methodStats.getMethodName(), 108 | methodStats.isDocumented(), methodStats.getDocumentedMembersPercent()); 109 | exportMembersDocStats(writer, methodStats.getParamsStats(), memberTypeFormat); 110 | 111 | if (methodStats.getThrownExceptionsStats().getMembersNumber() > 0) { 112 | exportMembersDocStats(writer, methodStats.getThrownExceptionsStats(), memberTypeFormat); 113 | } 114 | } 115 | } 116 | 117 | private void exportMembersDocStats(final PrintWriter writer, final MembersDocStats membersDocStats) { 118 | exportMembersDocStats(writer, membersDocStats, ""); 119 | } 120 | 121 | private void exportMembersDocStats(final PrintWriter writer, final MembersDocStats membersDocStats, final String memberTypeFormat) { 122 | if (membersDocStats.getMembersNumber() == 0 && !membersDocStats.isPrintIfNoMembers()) { 123 | return; 124 | } 125 | 126 | final String format = (Utils.isStringEmpty(memberTypeFormat) ? "\t\t%-20s" : memberTypeFormat) + 127 | " %6d Undocumented: %6d Documented: %6d (%.2f%%) \n"; 128 | writer.printf(format, 129 | membersDocStats.getType()+":", membersDocStats.getMembersNumber(), 130 | membersDocStats.getUndocumentedMembers(), 131 | membersDocStats.getDocumentedMembers(), membersDocStats.getDocumentedMembersPercent()); 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/exporter/DataExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.exporter; 17 | 18 | import com.manoelcampos.javadoc.coverage.CoverageDoclet; 19 | 20 | /** 21 | * An interface to implement JavaDoc Coverage reports in different formats such as HTML, CSV, JSON, etc. 22 | * 23 | * @author Manoel Campos da Silva Filho 24 | * @since 1.0.0 25 | */ 26 | public interface DataExporter { 27 | /** 28 | * The name to be used as default for the JavaDoc Coverage report if 29 | * a specific name is not given. 30 | * 31 | * @see CoverageDoclet#OUTPUT_NAME_OPTION 32 | */ 33 | String DEFAULT_OUTPUT_NAME = "javadoc-coverage"; 34 | 35 | /** 36 | * Gets the actual name to be used for the JavaDoc Coverage Report, 37 | * whether the default or given one. 38 | * 39 | * @return 40 | * @see #DEFAULT_OUTPUT_NAME 41 | */ 42 | String getReportFileName(); 43 | 44 | /** 45 | * Builds the JavaDoc Coverage Report to the file 46 | * specified by {@link #getReportFileName()}. 47 | * 48 | * @return 49 | */ 50 | boolean build(); 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/exporter/HtmlExporter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.exporter; 17 | 18 | import com.manoelcampos.javadoc.coverage.CoverageDoclet; 19 | import com.manoelcampos.javadoc.coverage.Utils; 20 | import com.manoelcampos.javadoc.coverage.stats.ClassDocStats; 21 | import com.manoelcampos.javadoc.coverage.stats.MembersDocStats; 22 | import com.manoelcampos.javadoc.coverage.stats.MethodDocStats; 23 | import com.sun.javadoc.PackageDoc; 24 | 25 | import java.util.List; 26 | 27 | /** 28 | * Exports the JavaDoc coverage report to an HTML file. 29 | * 30 | * @author Manoel Campos da Silva Filho 31 | * @since 1.0.0 32 | */ 33 | public class HtmlExporter extends AbstractDataExporter { 34 | public static final String COLUMNS = "%s%s%s%s%s%s%.2f%%\n"; 35 | 36 | public HtmlExporter(final CoverageDoclet doclet) { 37 | super(doclet, ".html"); 38 | } 39 | 40 | @Override 41 | protected void exportProjectDocumentationCoverageSummary() { 42 | getWriter().printf("" + COLUMNS + "", "Project Documentation Coverage", "", "", "", "", "", getStats().getDocumentedMembersPercent()); 43 | } 44 | 45 | @Override 46 | protected void header() { 47 | getWriter().println("\n"); 48 | getWriter().println(""); 49 | getWriter().println(" JavaDoc Coverage Report"); 50 | getWriter().println(" "); 51 | getWriter().println(" "); 52 | getWriter().println(" \n"); 53 | //https://github.com/maslianok/stickyRows 54 | getWriter().println(" \n"); 55 | getWriter().println(""); 56 | getWriter().println(""); 57 | getWriter().println("
"); 58 | getWriter().println("

JavaDoc Coverage Report

"); 59 | getWriter().println(""); 60 | getWriter().println(""); 61 | getWriter().println(""); 62 | getWriter().println(""); 63 | getWriter().println(""); 64 | getWriter().println(""); 65 | getWriter().println(""); 66 | } 67 | 68 | @Override 69 | protected void footer() { 70 | getWriter().println(""); 71 | getWriter().println("
Element TypeNamePackageDocumentable MembersUndocumentedDocumentedDocumented Percent
"); 72 | getWriter().println("
"); 73 | getWriter().println(""); 74 | 75 | getWriter().println("\n"); 76 | getWriter().println("\n"); 77 | getWriter().println("\n"); 78 | getWriter().println("\n"); 79 | getWriter().println(""); 80 | } 81 | 82 | @Override 83 | protected void exportPackagesDocStats() { 84 | exportMembersDocStatsSummary(getStats().getPackagesDocStats()); 85 | for (final PackageDoc doc : getStats().getPackagesDocStats().getPackagesDoc()) { 86 | getWriter().println(""); 87 | final Boolean documented = Utils.isNotStringEmpty(doc.getRawCommentText()); 88 | final double coverage = Utils.boolToInt(documented)*100; 89 | exportLine(2, "Package", doc.name(), "", "", "", documented.toString(), coverage); 90 | } 91 | } 92 | 93 | @Override 94 | protected void exportClassesDocStats() { 95 | exportMembersDocStatsSummary(getStats().getClassesDocStats()); 96 | for (final ClassDocStats classDocStats : getStats().getClassesDocStats().getClassesList()) { 97 | exportMembersDocStatsSummary(classDocStats, 2, classDocStats.getName(), classDocStats.getPackageName()); 98 | exportMembersDocStatsSummary(classDocStats.getFieldsStats(), 3); 99 | exportMethodsDocStats(classDocStats.getConstructorsStats()); 100 | exportMethodsDocStats(classDocStats.getMethodsStats()); 101 | } 102 | } 103 | 104 | private void exportMethodsDocStats(final List methods) { 105 | for (MethodDocStats m : methods) { 106 | exportMembersDocStatsSummary(m, 4, m.getMethodName(), ""); 107 | exportMembersDocStatsSummary(m.getParamsStats(), 5); 108 | exportMembersDocStatsSummary(m.getThrownExceptionsStats(), 5); 109 | } 110 | } 111 | 112 | private void exportMembersDocStatsSummary(final MembersDocStats membersDocStats, final int indentLevel) { 113 | exportMembersDocStatsSummary(membersDocStats, indentLevel, "",""); 114 | } 115 | 116 | private void exportMembersDocStatsSummary(final MembersDocStats membersDocStats) { 117 | exportMembersDocStatsSummary(membersDocStats, 1, "",""); 118 | } 119 | 120 | private void exportMembersDocStatsSummary(final MembersDocStats membersDocStats, final int indentLevel, final String name, final String pkg) { 121 | if(!membersDocStats.isPrintIfNoMembers() && membersDocStats.getMembersNumber() == 0){ 122 | return; 123 | } 124 | 125 | exportLine( 126 | indentLevel, membersDocStats.getType(), name, pkg, 127 | membersDocStats.getMembersNumber(), 128 | membersDocStats.getUndocumentedMembers(), 129 | membersDocStats.getDocumentedMembers(), 130 | membersDocStats.getDocumentedMembersPercent()); 131 | } 132 | 133 | private void exportLine(int indentLevel, String memberType, String name, String pkg, Long members, Long undocumented, Long documented, double documentedPercent){ 134 | exportLine(indentLevel, memberType, name, pkg, members.toString(), undocumented.toString(), documented.toString(), documentedPercent); 135 | } 136 | 137 | private void exportLine(int indentLevel, String memberType, String name, String pkg, String members, String undocumented, String documented, double documentedPercent){ 138 | getWriter().println(""); 139 | final String type = getIndentation(indentLevel) + memberType; 140 | getWriter().printf(COLUMNS, type, name, pkg, members, undocumented, documented, documentedPercent); 141 | getWriter().println(""); 142 | } 143 | 144 | private String getIndentation(final int indentLevel) { 145 | final int len = indentLevel*4 - 3; 146 | return String.format("%"+len+"s", "").replace(" ", " "); 147 | } 148 | 149 | @Override 150 | public void afterBuild() { 151 | System.out.printf("\nJavaDoc Coverage report saved to %s\n", getFile().getAbsolutePath()); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/ClassDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.*; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | /** 26 | * Computes statistics about the JavaDocs of a class, inner class, interface or enum 27 | * and its members, such as: fields, methods, constructors and annotations. 28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public class ClassDocStats extends MembersDocStats { 33 | /** 34 | * This value is added to the number of elements in order to count the class itself as an element 35 | * which can be documented. 36 | * 37 | * @see #getMembersNumber() 38 | */ 39 | private static final int CLASS_DOC = 1; 40 | 41 | private final ClassDoc doc; 42 | private final ClassMembersDocStats fieldsStats; 43 | private final ClassMembersDocStats enumsStats; 44 | private ClassMembersDocStats annotationsStats; 45 | 46 | private List methodsStats; 47 | private List constructorsStats; 48 | 49 | public ClassDocStats(final ClassDoc doc) { 50 | this.doc = doc; 51 | fieldsStats = new ClassMembersDocStats(doc.fields(false), "Fields"); 52 | enumsStats = new ClassMembersDocStats(doc.enumConstants(), "Enum Consts"); 53 | processMethodsDocsStats(doc); 54 | processConstructorsDocsStats(doc); 55 | processAnnotationsDocsStats(doc); 56 | } 57 | 58 | private void processAnnotationsDocsStats(ClassDoc doc) { 59 | if (doc instanceof AnnotationTypeDoc) { 60 | annotationsStats = new ClassMembersDocStats(((AnnotationTypeDoc) doc).elements(), "Annotations"); 61 | } else annotationsStats = new ClassMembersDocStats(new AnnotationTypeElementDoc[0], "Annotations"); 62 | } 63 | 64 | private void processConstructorsDocsStats(ClassDoc doc) { 65 | final ConstructorDoc[] constructors = doc.constructors(false); 66 | constructorsStats = new ArrayList<>(constructors.length); 67 | for (final ConstructorDoc constructor : constructors) { 68 | constructorsStats.add(new MethodDocStats(constructor)); 69 | } 70 | } 71 | 72 | private void processMethodsDocsStats(ClassDoc doc) { 73 | final MethodDoc[] methods = doc.methods(false); 74 | methodsStats = new ArrayList<>(methods.length); 75 | for (final MethodDoc method : methods) { 76 | methodsStats.add(new MethodDocStats(method)); 77 | } 78 | } 79 | 80 | @Override 81 | public long getDocumentedMembers() { 82 | return 83 | Utils.boolToInt(isDocumented()) + 84 | fieldsStats.getDocumentedMembers() + 85 | enumsStats.getDocumentedMembers() + 86 | getDocumentedMethodMembers(methodsStats) + 87 | getDocumentedMethodMembers(constructorsStats) + 88 | annotationsStats.getDocumentedMembers(); 89 | } 90 | 91 | @Override 92 | public long getMembersNumber() { 93 | return CLASS_DOC + 94 | fieldsStats.getMembersNumber() + 95 | enumsStats.getMembersNumber() + 96 | getMethodMembers(methodsStats) + 97 | getMethodMembers(constructorsStats) + 98 | annotationsStats.getMembersNumber(); 99 | } 100 | 101 | private long getDocumentedMethodMembers(final List methodOrConstructor) { 102 | return methodOrConstructor.stream().filter(MethodDocStats::isDocumented).count() + 103 | methodOrConstructor.stream().mapToLong(MethodDocStats::getDocumentedMembers).sum(); 104 | } 105 | 106 | /** 107 | * Gets the amount of documentable members from a given list of methods/constructors. 108 | * 109 | * @param methodOrConstructor a list containing the methods and constructors to get their number of members 110 | * @return the total number of members for the given list of methods/constructors 111 | * @see MethodDocStats#getMembersNumber() 112 | */ 113 | private long getMethodMembers(final List methodOrConstructor) { 114 | return methodOrConstructor.stream().mapToLong(MethodDocStats::getMembersNumber).sum(); 115 | } 116 | 117 | public String getName() { 118 | return doc.name(); 119 | } 120 | 121 | public String getPackageName() { 122 | return doc.containingPackage().name(); 123 | } 124 | 125 | @Override 126 | public String getType() { 127 | return doc.isInterface() ? "Interface" : doc.isEnum() ? "Enum" : "Class"; 128 | } 129 | 130 | public ClassMembersDocStats getFieldsStats() { 131 | return fieldsStats; 132 | } 133 | 134 | public ClassMembersDocStats getEnumsStats() { 135 | return enumsStats; 136 | } 137 | 138 | public ClassMembersDocStats getAnnotationsStats() { 139 | return annotationsStats; 140 | } 141 | 142 | public List getMethodsStats() { 143 | return Collections.unmodifiableList(methodsStats); 144 | } 145 | 146 | public List getConstructorsStats() { 147 | return Collections.unmodifiableList(constructorsStats); 148 | } 149 | 150 | public ClassDoc getDoc() { 151 | return doc; 152 | } 153 | 154 | @Override 155 | public boolean isDocumented() { 156 | return Utils.isElementDocumented(doc.getRawCommentText()); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/ClassMembersDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.Doc; 20 | 21 | import java.util.Arrays; 22 | import java.util.Objects; 23 | 24 | /** 25 | * Computes JavaDoc coverage statistics for specific type of members belonging to an owner. 26 | * An owner can be a class, interface or enum. 27 | * Members may be either fields, methods or constructors. 28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public class ClassMembersDocStats extends MembersDocStats { 33 | /** 34 | * The JavaDoc documentation for the members of the owner. 35 | */ 36 | private final Doc[] membersDocs; 37 | private final String membersType; 38 | 39 | /** 40 | * Instantiates an object to compute JavaDoc coverage statistics 41 | * for the members of a class, interface or enum. 42 | * 43 | * @param membersDocs the JavaDoc documentation for the members of the owner. 44 | * @param membersType the type of the members of the owner to compute JavaDoc coverage statistics. 45 | */ 46 | ClassMembersDocStats(final Doc[] membersDocs, final String membersType) { 47 | this.membersDocs = membersDocs; 48 | this.membersType = membersType; 49 | } 50 | 51 | /** 52 | * Gets the number of members which are explicitly declared into the source code, 53 | * from a list of given members. 54 | * 55 | * The length of the given array cannot be used to this purpose 56 | * because some elements such as default no-args constructors are not directly declared 57 | * into the source class but are counted as a member. 58 | * This way, it may count as a non-documented element 59 | * while it doesn't even exist into the source code. 60 | */ 61 | @Override 62 | public long getMembersNumber() { 63 | /* 64 | * @todo the method is not working as expected. It always returns the length of the array. 65 | * The side-effect is that default no-args constructors (which aren't directly declared into 66 | * a class source code) will be computed as undocumented. 67 | */ 68 | return Arrays.stream(membersDocs) 69 | .map(Doc::position) 70 | .filter(Objects::nonNull) 71 | .count(); 72 | } 73 | 74 | @Override 75 | public long getDocumentedMembers() { 76 | return Arrays.stream(membersDocs).map(Doc::getRawCommentText).filter(Utils::isNotStringEmpty).count(); 77 | } 78 | 79 | @Override 80 | public String getType() { 81 | return membersType; 82 | } 83 | 84 | /** 85 | * A set of class members doesn't have documentation, 86 | * only each individual member may have. 87 | * @return 88 | */ 89 | @Override 90 | public boolean isDocumented() { 91 | return false; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/ClassesDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.ClassDoc; 20 | import com.sun.javadoc.Doc; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Collections; 24 | import java.util.List; 25 | 26 | /** 27 | * Computes JavaDoc coverage statistics for a list of classes. 28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public class ClassesDocStats extends MembersDocStats { 33 | private final List classesDocStats; 34 | 35 | /** 36 | * Instantiates an object to compute JavaDoc coverage statistics for a list of classes. 37 | * 38 | * @param docs an array of elements which enables reading the classes' JavaDoc documentation 39 | */ 40 | public ClassesDocStats(final ClassDoc[] docs){ 41 | classesDocStats = new ArrayList<>(docs.length); 42 | for (final ClassDoc doc : docs) { 43 | classesDocStats.add(new ClassDocStats(doc)); 44 | } 45 | } 46 | 47 | @Override 48 | public long getMembersNumber() { 49 | return classesDocStats.size(); 50 | } 51 | 52 | @Override 53 | public String getType() { 54 | return "Classes/Interfaces/Enums"; 55 | } 56 | 57 | @Override 58 | public long getDocumentedMembers() { 59 | return classesDocStats.stream().map(ClassDocStats::getDoc).map(Doc::getRawCommentText).filter(Utils::isNotStringEmpty).count(); 60 | } 61 | 62 | /** 63 | * Gets a List where each element represents the individual JavaDoc coverage statistics for a specific class. 64 | * 65 | * @return a List of class's JavaDoc coverage statistics 66 | */ 67 | public List getClassesList() { 68 | return Collections.unmodifiableList(classesDocStats); 69 | } 70 | 71 | /** 72 | * A set of classes doesn't have documentation, 73 | * only each individual class may have. 74 | * @return 75 | */ 76 | @Override 77 | public boolean isDocumented() { 78 | return false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/DocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | 20 | /** 21 | * An interface to be implemented by classes 22 | * computing JavaDoc coverage statistics. 23 | * 24 | * @author Manoel Campos da Silva Filho 25 | * @since 1.0.0 26 | */ 27 | public interface DocStats { 28 | /** 29 | * The type of the element to which JavaDoc coverage statistics is being computed, 30 | * whether a class, interface, field, method, parameter, etc. 31 | * @return the type of elements 32 | */ 33 | String getType(); 34 | 35 | /** 36 | * Gets the number of documented members contained into 37 | * the object for which the JavaDoc coverage statistics is being computed. 38 | * 39 | * @return the number of members having JavaDoc documentation 40 | */ 41 | long getDocumentedMembers(); 42 | 43 | /** 44 | * Gets the number of undocumented members contained into 45 | * the object for which the JavaDoc coverage statistics is being computed. 46 | * 47 | * @return the number of members not having JavaDoc documentation 48 | */ 49 | default long getUndocumentedMembers() { 50 | return getMembersNumber() - getDocumentedMembers(); 51 | } 52 | 53 | /** 54 | * Gets the percentage of documented members contained into 55 | * the object for which the JavaDoc coverage statistics is being computed. 56 | * 57 | * @return the percentage of documented members, in scale from 0 to 100. 58 | */ 59 | default double getDocumentedMembersPercent(){ 60 | return Utils.computePercentage(getDocumentedMembers(), getMembersNumber()); 61 | } 62 | 63 | /** 64 | * Gets the total number of members contained into 65 | * the object for which the JavaDoc coverage statistics is being computed. 66 | * 67 | * @return the total number of members 68 | */ 69 | long getMembersNumber(); 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/JavaDocsStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.ClassDoc; 20 | import com.sun.javadoc.RootDoc; 21 | 22 | /** 23 | * Computes JavaDoc coverage statistics for Java files received by the JavaDoc tool. 24 | * 25 | *

It's the main class to store JavaDocs statistics for any kind of 26 | * documentable element into a Java source file. 27 | * It includes the computed statistics for an entire Java project 28 | * parsed by the JavaDoc Tool.

29 | * 30 | * @author Manoel Campos da Silva Filho 31 | * @since 1.0.0 32 | */ 33 | public class JavaDocsStats implements DocStats { 34 | /** 35 | * Stores the root of the program structure information. 36 | */ 37 | private final RootDoc rootDoc; 38 | 39 | private final PackagesDocStats packagesDocStats; 40 | private final ClassesDocStats classesDocStats; 41 | 42 | /** 43 | * Instantiates an object to compute JavaDoc coverage statistics for all Java files 44 | * received by the JavaDoc tool. 45 | * 46 | * @param rootDoc root element which enables reading JavaDoc documentation 47 | */ 48 | public JavaDocsStats(final RootDoc rootDoc) { 49 | this.rootDoc = rootDoc; 50 | this.classesDocStats = new ClassesDocStats(rootDoc.classes()); 51 | this.packagesDocStats = computePackagesDocsStats(); 52 | } 53 | 54 | /** 55 | * Computes JavaDoc coverage statistics for detected packages. 56 | * 57 | * @return packages' JavaDoc coverage statistics 58 | */ 59 | private PackagesDocStats computePackagesDocsStats() { 60 | final PackagesDocStats stats = new PackagesDocStats(); 61 | for (final ClassDoc doc : rootDoc.classes()) { 62 | stats.addPackageDoc(doc.containingPackage()); 63 | } 64 | 65 | return stats; 66 | } 67 | 68 | /** 69 | * Gets the object containing JavaDoc coverage statistics for detected packages. 70 | * 71 | * @return packages' JavaDoc coverage statistics 72 | * @see #computePackagesDocsStats() 73 | */ 74 | public PackagesDocStats getPackagesDocStats() { 75 | return packagesDocStats; 76 | } 77 | 78 | /** 79 | * Gets the object containing JavaDoc coverage statistics for detected classes. 80 | * 81 | * @return classes' JavaDoc coverage statistics 82 | */ 83 | public ClassesDocStats getClassesDocStats() { return classesDocStats; } 84 | 85 | @Override 86 | public String getType() { 87 | return "Project JavaDoc Statistics"; 88 | } 89 | 90 | @Override 91 | public long getDocumentedMembers() { 92 | return packagesDocStats.getDocumentedMembers() + classesDocStats.getDocumentedMembers(); 93 | } 94 | 95 | @Override 96 | public double getDocumentedMembersPercent() { 97 | return Utils.mean(packagesDocStats.getDocumentedMembersPercent(), classesDocStats.getDocumentedMembersPercent()); 98 | } 99 | 100 | @Override 101 | public long getMembersNumber() { 102 | return classesDocStats.getMembersNumber() + packagesDocStats.getMembersNumber(); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/MembersDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | /** 19 | * An abstract class to compute JavaDocs coverage statistics for a list of members 20 | * belonging to another object, which is called the owner. 21 | * 22 | *

In the case the owner of the members is: 23 | *

    24 | *
  • a class, computes statistics for its fields, methods and so on.
  • 25 | *
  • a method, computes statistics for its parameters and thrown exceptions.
  • 26 | *
27 | *

28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public abstract class MembersDocStats implements DocStats { 33 | private boolean printIfNoMembers; 34 | 35 | /** 36 | * Checks if the the owner of the members has a documentation itself. 37 | * 38 | * @return true if the owner has documentation, false otherwise 39 | */ 40 | public abstract boolean isDocumented(); 41 | 42 | /** 43 | * Checks if JavaDoc coverage statistics should be printed if the owner has no member. 44 | * 45 | * @return true if statistics should be printed even if the owner has no member, false if 46 | * statistics shouldn't be printed if the owner has no member 47 | */ 48 | public final boolean isPrintIfNoMembers() { 49 | return this.printIfNoMembers; 50 | } 51 | 52 | /** 53 | * Enables printing JavaDoc coverage statistics even if the owner has no member. 54 | */ 55 | public final void enablePrintIfNoMembers() { 56 | this.printIfNoMembers = true; 57 | } 58 | 59 | /** 60 | * Disables printing JavaDoc coverage statistics if the owner has no member. 61 | */ 62 | public final void disablePrintIfNoMembers() { 63 | this.printIfNoMembers = false; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/MethodDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.ExecutableMemberDoc; 20 | import com.sun.javadoc.MethodDoc; 21 | import com.sun.javadoc.Tag; 22 | 23 | import java.util.Arrays; 24 | 25 | /** 26 | * Computes JavaDoc coverage statistics for a method/constructor 27 | * and its members, namely parameters and thrown exceptions. 28 | * 29 | * @author Manoel Campos da Silva Filho 30 | * @since 1.0.0 31 | */ 32 | public class MethodDocStats extends MembersDocStats { 33 | /** 34 | * This value is added to the number of elements in order to count the method itself as an element 35 | * which can be documented. 36 | * 37 | * @see #getMembersNumber() 38 | * @see #getDocumentedMembersPercent() 39 | */ 40 | private static final int METHOD_DOC = 1; 41 | 42 | private final ExecutableMemberDoc doc; 43 | private final MethodParamsDocStats paramsStats; 44 | private final MethodExceptionsDocStats thrownExceptionsStats; 45 | 46 | /** 47 | * Instantiates an object to compute JavaDoc coverage statistics for a method/constructor. 48 | * 49 | * @param doc the element which enables reading the method's JavaDoc documentation 50 | */ 51 | MethodDocStats(final ExecutableMemberDoc doc) { 52 | this.doc = doc; 53 | this.paramsStats = new MethodParamsDocStats(doc); 54 | this.thrownExceptionsStats = new MethodExceptionsDocStats(doc); 55 | this.enablePrintIfNoMembers(); 56 | } 57 | 58 | public String getMethodName() { 59 | return doc.name(); 60 | } 61 | 62 | @Override 63 | public String getType() { 64 | return doc.isConstructor() ? "Constructor" : "Method"; 65 | } 66 | 67 | /** 68 | * Gets the JavaDoc coverage statistics for the method/constructor's parameters. 69 | * 70 | * @return 71 | */ 72 | public MethodParamsDocStats getParamsStats() { 73 | return paramsStats; 74 | } 75 | 76 | /** 77 | * Gets the JavaDoc coverage statistics for the exceptions thrown by the method/constructor. 78 | * 79 | * @return 80 | */ 81 | public MethodExceptionsDocStats getThrownExceptionsStats() { 82 | return thrownExceptionsStats; 83 | } 84 | 85 | @Override 86 | public long getDocumentedMembers() { 87 | final int returnCount = (!isVoidMethodOrConstructor() && isReturnDocumented()) ? 1 : 0; 88 | final long documentedMembers = Utils.boolToInt(isDocumented()) + 89 | paramsStats.getDocumentedMembers() + 90 | thrownExceptionsStats.getDocumentedMembers() + 91 | returnCount; 92 | 93 | /* If an overridden method isn't documented at all, it doesn't matter because 94 | * its documentation is optional. The superclass is accountable to document 95 | * the method. This way, the method is counted as completely documented. 96 | */ 97 | if (isOverridden() && documentedMembers == 0) { 98 | return getMembersNumber(); 99 | } 100 | 101 | return documentedMembers; 102 | } 103 | 104 | private boolean isReturnDocumented() { 105 | return Arrays.stream(doc.tags()).filter(t -> t.name().equals("@return")).map(Tag::text).anyMatch(Utils::isNotStringEmpty); 106 | } 107 | 108 | private boolean isOverridden() { 109 | return doc.isMethod() && ((MethodDoc) doc).overriddenMethod() != null; 110 | } 111 | 112 | @Override 113 | public double getDocumentedMembersPercent() { 114 | return Utils.computePercentage(getDocumentedMembers(), getMembersNumber()); 115 | } 116 | 117 | /** 118 | * Checks if the method is void or is a constructor. 119 | * Either ways, it doesn't have a return value to be documented. 120 | * 121 | * @return true if the method is void or is a constructor, false otherwise 122 | */ 123 | private boolean isVoidMethodOrConstructor() { 124 | return isVoidMethod() || doc.isConstructor(); 125 | } 126 | 127 | private boolean isVoidMethod() { 128 | return doc.isMethod() && ((MethodDoc) doc).returnType() == null; 129 | } 130 | 131 | @Override 132 | public long getMembersNumber() { 133 | final int returnCount = isVoidMethodOrConstructor() ? 0 : 1; 134 | 135 | return METHOD_DOC + 136 | paramsStats.getMembersNumber() + 137 | thrownExceptionsStats.getMembersNumber() + 138 | returnCount; 139 | } 140 | 141 | @Override 142 | public boolean isDocumented() { 143 | return Utils.isElementDocumented(doc.getRawCommentText()); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/MethodExceptionsDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.sun.javadoc.ClassDoc; 19 | import com.sun.javadoc.ExecutableMemberDoc; 20 | import com.sun.javadoc.Tag; 21 | 22 | import java.util.Arrays; 23 | import java.util.regex.Matcher; 24 | import java.util.regex.Pattern; 25 | import java.util.stream.Stream; 26 | 27 | /** 28 | * Computes JavaDoc coverage statistics for the exceptions thrown by a specific method. 29 | * 30 | * @author Manoel Campos da Silva Filho 31 | * @since 1.0.0 32 | */ 33 | public class MethodExceptionsDocStats extends MethodTagsDocStats { 34 | 35 | /** 36 | * Instantiates an object to compute JavaDoc coverage statistics for the exceptions thrown 37 | * by a method/constructor. 38 | * 39 | * @param doc an object which enables reading the JavaDoc documentation for the method the exceptions belong to 40 | */ 41 | MethodExceptionsDocStats(final ExecutableMemberDoc doc) { 42 | super(doc); 43 | } 44 | 45 | @Override 46 | public String getType() { 47 | return "Exceptions"; 48 | } 49 | 50 | /** 51 | * Gets the total number of exceptions in the method for which the JavaDoc 52 | * coverage statistics is being computed. 53 | * 54 | *

55 | * There may be documented exceptions which aren't declared. 56 | * Usually, undeclared exceptions are unchecked exceptions, 57 | * which aren't required to be declared. 58 | * Due to such conditions, the number of existing exceptions will be those:
59 | * declared but not documented + documented but not declared + documented and declared. 60 | *

61 | * @return the total number of exceptions 62 | */ 63 | @Override 64 | public long getMembersNumber() { 65 | return getDeclaredButNotDocumentedExceptionsNumber() + 66 | getDocumentedButNotDeclaredExceptionsNumber() + 67 | getDeclaredAndDocumentedExceptionsNumber(); 68 | } 69 | 70 | /** 71 | * Gets the number of exceptions which are documented in the JavaDoc but not actually declared in the 72 | * method signature. 73 | * 74 | *

Unchecked exceptions can be in this situation, since they are not required to be declared. 75 | * If a checked exception is documented but not declared, usually the IDEs report an issue 76 | * that the developer should fix. 77 | *

78 | * 79 | * @return 80 | */ 81 | private long getDocumentedButNotDeclaredExceptionsNumber() { 82 | return 83 | getDocumentedTagStream() 84 | .filter(tag -> getDeclaredExceptionsStream().noneMatch(ex -> isExceptionEqualsToJavaDocTag(ex, tag))) 85 | .count(); 86 | } 87 | 88 | /** 89 | * Gets the number of exceptions which are declared but not documented in the JavaDoc. 90 | * @return 91 | */ 92 | private long getDeclaredButNotDocumentedExceptionsNumber() { 93 | return getDeclaredExceptionsStream() 94 | .filter(ex -> getDocumentedTagStream().noneMatch(tag -> isExceptionEqualsToJavaDocTag(ex, tag))) 95 | .count(); 96 | } 97 | 98 | /** 99 | * Gets the number of exceptions which are both declared and documented in the JavaDoc. 100 | * @return 101 | */ 102 | private long getDeclaredAndDocumentedExceptionsNumber() { 103 | return getDeclaredExceptionsStream() 104 | .filter(ex -> getDocumentedTagStream().anyMatch(tag -> isExceptionEqualsToJavaDocTag(ex, tag))) 105 | .count(); 106 | } 107 | 108 | /** 109 | * Gets a Stream of thrown exceptions declared in the method's signature. 110 | * 111 | * @return 112 | */ 113 | private Stream getDeclaredExceptionsStream() { 114 | return Arrays.stream(getDoc().thrownExceptions()); 115 | } 116 | 117 | /** 118 | * Checks if a given exception is equals to a given @throws tag get from a method JavaDoc, 119 | * meaning the tag represents the documentation for that exception. 120 | * 121 | * @param exception the exception to check 122 | * @param tag the JavaDoc @throws tag to check 123 | * @return true if the exception matches with the JavaDoc @throws tag 124 | */ 125 | private boolean isExceptionEqualsToJavaDocTag(final ClassDoc exception, final Tag tag) { 126 | /* 127 | The exception class parsed by the Doclet always starts with the package name, 128 | even if the package is not included in the throws clause. 129 | On the other hand, the JavaDoc tag used by a developer to document the 130 | exception usually isn't prefixed with its package. 131 | */ 132 | return exception.toString().endsWith(getExceptionClassFromTag(tag)); 133 | } 134 | 135 | /** 136 | * Gets the class of an exception from its JavaDoc tag. 137 | * @param tag the JavaDoc tag representing the documentation of a method's exception 138 | * @return the class of the exception 139 | */ 140 | private String getExceptionClassFromTag(final Tag tag) { 141 | final Matcher matcher = Pattern.compile("\\w*").matcher(tag.text()); 142 | return matcher.find() ? matcher.group() : tag.text(); 143 | } 144 | 145 | @Override 146 | public String getTagName() { 147 | return "@throws"; 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/MethodParamsDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.sun.javadoc.ExecutableMemberDoc; 19 | 20 | /** 21 | * Computes JavaDoc coverage statistics for parameters from a specific method. 22 | * 23 | * @author Manoel Campos da Silva Filho 24 | * @since 1.0.0 25 | */ 26 | public class MethodParamsDocStats extends MethodTagsDocStats { 27 | 28 | /** 29 | * Instantiates an object to compute JavaDoc coverage statistics for the params 30 | * of a method/constructor. 31 | * 32 | * @param doc an object which enables reading the JavaDoc documentation for the method the params belong to 33 | */ 34 | MethodParamsDocStats(final ExecutableMemberDoc doc) { 35 | super(doc); 36 | } 37 | 38 | @Override 39 | public long getMembersNumber() { 40 | return getDoc().parameters().length; 41 | } 42 | 43 | @Override 44 | public String getTagName() { 45 | return "@param"; 46 | } 47 | 48 | @Override 49 | public String getType() { 50 | return "Params"; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/MethodTagsDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.ExecutableMemberDoc; 20 | import com.sun.javadoc.Tag; 21 | 22 | import java.util.Arrays; 23 | import java.util.stream.Stream; 24 | 25 | /** 26 | * An abstract class to compute JavaDoc statistics for a set of tags 27 | * associated to a method/constructor, such as the {@code @param} and {@code @throws} tags. 28 | * 29 | * Each {@link MethodTagsDocStats} sub-class is accountable to compute 30 | * statistics to a specific kind of tag such as method's parameters or thrown exceptions. 31 | * 32 | * @author Manoel Campos da Silva Filho 33 | * @since 1.0.0 34 | */ 35 | public abstract class MethodTagsDocStats extends MembersDocStats { 36 | /** 37 | * JavaDoc documentation for the method the tags belong to. 38 | */ 39 | private final ExecutableMemberDoc doc; 40 | 41 | /** 42 | * Instantiates an object to compute JavaDoc coverage statistics for the tags 43 | * of a method/constructor. 44 | * 45 | * @param doc an object which enables reading the JavaDoc documentation for the method the tags belong to 46 | */ 47 | MethodTagsDocStats(final ExecutableMemberDoc doc) { 48 | super(); 49 | this.doc = doc; 50 | } 51 | 52 | /** 53 | * Gets the name of the tag associated to this object for which 54 | * JavaDoc coverage statistics will be computed, for instance, 55 | * "param" or "throws" tags. 56 | * 57 | * @return 58 | */ 59 | public abstract String getTagName(); 60 | 61 | @Override 62 | public long getDocumentedMembers() { 63 | return getDocumentedTagStream().count(); 64 | } 65 | 66 | /** 67 | * Gets a Stream of all documented method Tags for the method. 68 | * @return the documented Tag Stream 69 | */ 70 | protected Stream getDocumentedTagStream() { 71 | return Arrays.stream(getDoc().tags()) 72 | .filter(tag -> getTagName().equals(tag.name())) 73 | .filter(tag -> Utils.isNotStringEmpty(tag.text())); 74 | } 75 | 76 | /** 77 | * Gets the element which enables reading the method's JavaDoc documentation. 78 | * 79 | * @return the method's JavaDoc documentation element 80 | */ 81 | protected ExecutableMemberDoc getDoc() { 82 | return doc; 83 | } 84 | 85 | /** 86 | * A set of tags doesn't have documentation. 87 | * Only each individual tag may have. 88 | * 89 | * @return always false 90 | */ 91 | @Override 92 | public boolean isDocumented() { 93 | return false; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/PackagesDocStats.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.manoelcampos.javadoc.coverage.stats; 17 | 18 | import com.manoelcampos.javadoc.coverage.Utils; 19 | import com.sun.javadoc.PackageDoc; 20 | 21 | import java.util.Collections; 22 | import java.util.HashSet; 23 | import java.util.Set; 24 | 25 | /** 26 | * Computes JavaDoc statistics for a set of packages. 27 | * 28 | * @author Manoel Campos da Silva Filho 29 | * @since 1.0.0 30 | */ 31 | public class PackagesDocStats extends MembersDocStats { 32 | private final Set packagesDoc; 33 | 34 | public PackagesDocStats(){ 35 | this.packagesDoc = new HashSet<>(); 36 | } 37 | 38 | /** 39 | * Adds an element to the Set of elements containing packages' JavaDocs. 40 | * 41 | * @param doc the package's JavaDoc element to add to the Set 42 | */ 43 | public void addPackageDoc(final PackageDoc doc){ 44 | packagesDoc.add(doc); 45 | } 46 | 47 | @Override 48 | public String getType() { 49 | return "Packages"; 50 | } 51 | 52 | @Override 53 | public long getMembersNumber() { 54 | return packagesDoc.size(); 55 | } 56 | 57 | @Override 58 | public long getDocumentedMembers() { 59 | return packagesDoc.stream().map(PackageDoc::getRawCommentText).filter(Utils::isNotStringEmpty).count(); 60 | } 61 | 62 | /** 63 | * Gets a Set of elements containing packages' JavaDocs. 64 | * 65 | * @return the Set of packages' JavaDocs 66 | */ 67 | public Set getPackagesDoc() { 68 | return Collections.unmodifiableSet(packagesDoc); 69 | } 70 | 71 | /** 72 | * A set of packages doesn't have documentation, 73 | * only each individual package may have. 74 | * @return 75 | */ 76 | @Override 77 | public boolean isDocumented() { 78 | return false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/manoelcampos/javadoc/coverage/stats/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2017 Manoel Campos da Silva Filho 3 | * 4 | * Licensed under the General Public License Version 3 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.gnu.org/licenses/gpl-3.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Contains {@link com.manoelcampos.javadoc.coverage.stats.DocStats} classes 19 | * used to compute JavaDoc coverage statistics for Java elements such as 20 | * classes, interfaces, fields, methods, parameters, etc. 21 | * 22 | * @author Manoel Campos da Silva Filho 23 | */ 24 | package com.manoelcampos.javadoc.coverage.stats; --------------------------------------------------------------------------------