From 33788ce247efc3b16596fd5e6aa63b425c102a12 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Tue, 23 Aug 2016 12:48:19 -0700 Subject: [PATCH 01/15] (maint) Update gitignore to ignore RubyMine and rvm/rbenv files. Adding `.idea/` and `.ruby-version` to gitignore. Also adding `doc/` for YARD output. Excluding VIM tags only in the root. --- .gitignore | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 936d40a..93e8f9a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ tmtags ## VIM *.swp -tags +/tags ## BUNDLER .bundle @@ -24,3 +24,12 @@ Gemfile.lock ## MODULE BUILDS **/pkg + +## RubyMine +/.idea/ + +## rvm/rbenv +/.ruby-version + +## YARD output +/doc/ From 56f266db4b8ca65bd240dcdaf3e80d8e4f01a4ed Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Tue, 23 Aug 2016 12:55:40 -0700 Subject: [PATCH 02/15] (maint) Rename puppetlab-strings to puppet-strings where appropriate. This commit changes the source and documentation to reference this project as `puppet-strings` rather than `puppetlabs-strings`. This makes the source and project match the gem name. --- .rubocop.yml | 2 +- .yardopts | 4 +- CHANGELOG.md | 4 +- COMMITTERS.md | 14 ++-- CONTRIBUTING.md | 6 +- README.md | 22 +++---- lib/puppet-strings/rake_tasks.rb | 6 +- lib/puppet-strings/rake_tasks/generate.rb | 12 ++-- lib/puppet/face/strings.rb | 10 +-- lib/puppet_x/puppet/strings.rb | 64 +++++++++++++++++++ .../{puppetlabs => puppet}/strings/actions.rb | 4 +- .../strings/pops/yard_statement.rb | 2 +- .../strings/pops/yard_transformer.rb | 6 +- .../{puppetlabs => puppet}/strings/util.rb | 10 +-- .../yard/code_objects/defined_type_object.rb | 2 +- .../yard/code_objects/host_class_object.rb | 4 +- .../yard/code_objects/method_object.rb | 0 .../yard/code_objects/provider_object.rb | 2 +- .../code_objects/puppet_namespace_object.rb | 2 +- .../strings/yard/code_objects/type_object.rb | 2 +- .../strings/yard/core_ext/yard.rb | 3 +- .../strings/yard/handlers/base.rb | 6 +- .../yard/handlers/defined_type_handler.rb | 2 +- .../strings/yard/handlers/heredoc_helper.rb | 4 +- .../yard/handlers/host_class_handler.rb | 2 +- .../strings/yard/handlers/provider_handler.rb | 4 +- .../handlers/puppet_3x_function_handler.rb | 4 +- .../handlers/puppet_4x_function_handler.rb | 6 +- .../strings/yard/handlers/type_handler.rb | 8 +-- .../strings/yard/json_registry_store.rb | 0 .../strings/yard/monkey_patches.rb | 0 .../strings/yard/parser.rb | 8 +-- .../default/definedtype/html/docstring.erb | 0 .../default/definedtype/html/header.erb | 0 .../definedtype/html/parameter_details.erb | 0 .../default/definedtype/html/setup.rb | 0 .../templates/default/definedtype/setup.rb | 0 .../default/fulldoc/html/full_list_class.erb | 0 .../html/full_list_puppet_manifest.erb | 0 .../fulldoc/html/full_list_puppet_plugin.erb | 0 .../html/full_list_puppet_provider.erb | 0 .../fulldoc/html/full_list_puppet_type.erb | 0 .../templates/default/fulldoc/html/setup.rb | 2 +- .../default/hostclass/html/box_info.erb | 0 .../templates/default/hostclass/html/setup.rb | 0 .../default/hostclass/html/subclasses.erb | 0 .../yard/templates/default/hostclass/setup.rb | 0 .../yard/templates/default/html_helper.rb | 0 .../templates/default/layout/html/setup.rb | 0 .../default/method_details/html/header.erb | 0 .../templates/default/method_details/setup.rb | 2 +- .../default/method_details/text/header.erb | 0 .../default/provider/html/command_details.erb | 0 .../default/provider/html/confine_details.erb | 0 .../default/provider/html/default_details.erb | 0 .../default/provider/html/docstring.erb | 0 .../default/provider/html/feature_details.erb | 0 .../default/provider/html/header.erb | 0 .../templates/default/provider/html/setup.rb | 0 .../yard/templates/default/provider/setup.rb | 0 .../default/puppetnamespace/html/box_info.erb | 0 .../default/puppetnamespace/html/header.erb | 0 .../html/method_details_list.erb | 0 .../puppetnamespace/html/method_summary.erb | 0 .../default/puppetnamespace/html/setup.rb | 0 .../default/puppetnamespace/setup.rb | 0 .../yard/templates/default/template_helper.rb | 0 .../templates/default/type/html/docstring.erb | 0 .../templates/default/type/html/header.erb | 0 .../default/type/html/parameter_details.erb | 0 .../default/type/html/provider_details.erb | 0 .../yard/templates/default/type/html/setup.rb | 0 .../yard/templates/default/type/setup.rb | 0 lib/puppet_x/puppetlabs/strings.rb | 64 ------------------- .../strings/yard/tags/directives.rb | 9 --- puppet-strings.gemspec | 6 +- spec/spec_helper.rb | 2 +- .../strings/pops_spec.rb | 10 +-- .../strings/yard/defined_type_handler_spec.rb | 4 +- .../lib/test.rb | 0 .../lib/test.rb | 0 .../test-param-names-differ/lib/test.rb | 0 .../lib/test.rb | 0 .../lib/test.rb | 0 .../test-param-names-match/lib/test.rb | 0 .../yard/examples/test/manifests/init.pp | 0 .../strings/yard/host_class_handler_spec.rb | 4 +- .../yard/puppet_3x_function_handler_spec.rb | 4 +- .../yard/puppet_4x_function_handler_spec.rb | 4 +- .../strings/yard/template_helper_spec.rb | 16 ++--- .../strings/yard/type_handler_spec.rb | 4 +- 91 files changed, 173 insertions(+), 183 deletions(-) create mode 100644 lib/puppet_x/puppet/strings.rb rename lib/puppet_x/{puppetlabs => puppet}/strings/actions.rb (97%) rename lib/puppet_x/{puppetlabs => puppet}/strings/pops/yard_statement.rb (97%) rename lib/puppet_x/{puppetlabs => puppet}/strings/pops/yard_transformer.rb (84%) rename lib/puppet_x/{puppetlabs => puppet}/strings/util.rb (85%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/defined_type_object.rb (84%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/host_class_object.rb (77%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/method_object.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/provider_object.rb (82%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/puppet_namespace_object.rb (93%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/code_objects/type_object.rb (91%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/core_ext/yard.rb (97%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/base.rb (56%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/defined_type_handler.rb (88%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/heredoc_helper.rb (95%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/host_class_handler.rb (94%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/provider_handler.rb (95%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/puppet_3x_function_handler.rb (90%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/puppet_4x_function_handler.rb (97%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/handlers/type_handler.rb (97%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/json_registry_store.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/monkey_patches.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/parser.rb (64%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/definedtype/html/docstring.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/definedtype/html/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/definedtype/html/parameter_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/definedtype/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/definedtype/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/full_list_class.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/fulldoc/html/setup.rb (94%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/hostclass/html/box_info.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/hostclass/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/hostclass/html/subclasses.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/hostclass/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/html_helper.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/layout/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/method_details/html/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/method_details/setup.rb (91%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/method_details/text/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/command_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/confine_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/default_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/docstring.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/feature_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/provider/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/html/box_info.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/html/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/html/method_summary.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/puppetnamespace/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/template_helper.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/html/docstring.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/html/header.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/html/parameter_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/html/provider_details.erb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/html/setup.rb (100%) rename lib/puppet_x/{puppetlabs => puppet}/strings/yard/templates/default/type/setup.rb (100%) delete mode 100644 lib/puppet_x/puppetlabs/strings.rb delete mode 100644 lib/puppet_x/puppetlabs/strings/yard/tags/directives.rb rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/pops_spec.rb (79%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/defined_type_handler_spec.rb (93%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-differ/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-match-with-types/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test-param-names-match/lib/test.rb (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/examples/test/manifests/init.pp (100%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/host_class_handler_spec.rb (95%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/puppet_3x_function_handler_spec.rb (91%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/puppet_4x_function_handler_spec.rb (97%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/template_helper_spec.rb (84%) rename spec/unit/puppet_x/{puppetlabs => puppet}/strings/yard/type_handler_spec.rb (92%) diff --git a/.rubocop.yml b/.rubocop.yml index 56eb8da..dd88b39 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,7 +2,7 @@ AllCops: Exclude: # Ignore HTML related things - '**/*.erb' - - 'lib/puppetx/puppetlabs/strings/yard/templates/**/*' + - 'lib/puppetx/puppet/strings/yard/templates/**/*' Lint/ConditionPosition: Enabled: true diff --git a/.yardopts b/.yardopts index e30cb06..bddb273 100644 --- a/.yardopts +++ b/.yardopts @@ -1,2 +1,2 @@ ---exclude lib/puppetx/puppetlabs/strings/yard/templates/ ---exclude lib/puppetx/puppetlabs/strings/yard/code_objects/host_class_object.rb +--exclude lib/puppetx/puppet/strings/yard/templates/ +--exclude lib/puppetx/puppet/strings/yard/code_objects/host_class_object.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 413df44..0e91af0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ All related tickets can be found under the [PDOC][PDOC JIRA] JIRA project with t ###Features - Support for JSON output **(PDOC-23)** - Strings now has the ability to produce a JSON representation of a given puppet module - - The details of the JSON schema can be found [here](https://github.com/puppetlabs/puppetlabs-strings/blob/master/json_dom.md) - - For details on how to generate JSON, see the [README](https://github.com/puppetlabs/puppetlabs-strings/blob/master/README.md#running-puppet-strings) + - The details of the JSON schema can be found [here](https://github.com/puppetlabs/puppet-strings/blob/master/json_dom.md) + - For details on how to generate JSON, see the [README](https://github.com/puppetlabs/puppet-strings/blob/master/README.md#running-puppet-strings) - Migrate to ruby gems as a distribution method **(PDOC-28)** - This is the last release of strings that will be available as a puppet module - The 0.4.0 release will be released concurrently as a ruby gem diff --git a/COMMITTERS.md b/COMMITTERS.md index b7a6b77..03a2a64 100644 --- a/COMMITTERS.md +++ b/COMMITTERS.md @@ -53,9 +53,9 @@ merged. **security** - Where critical security fixes are merged. These change sets will then be merged into release branches independently from one another. (i.e. no merging up). Please do not submit pull requests against the security branch -and instead report all security related issues to security@puppetlabs.com as +and instead report all security related issues to security@puppet.com as per our security policy published at -[https://puppetlabs.com/security/](https://puppetlabs.com/security/). +[https://puppet.com/security/](https://puppet.com/security/). Committer Guide ==== @@ -84,8 +84,8 @@ applied to earlier minor releases of a major release, but the patches should first be merged into the `security` branch. Security patches should be merged by Puppet Labs staff members. Pull requests should not be submitted with the security branch as the base branch. Please send all security related -information or patches to security@puppetlabs.com as per our [Security -Policy](https://puppetlabs.com/security/). +information or patches to security@puppet.com as per our [Security +Policy](https://puppet.com/security/). The CI systems are configured to run against `master`. Over time, this branch will refer to different versions, but its name will remain fixed to avoid having @@ -118,7 +118,7 @@ This section aims to provide guidelines for being a good commit citizen by paying attention to our automated build tools. * Don’t push on a broken build. (A broken build is defined as a failing job - in the [Puppet FOSS](https://jenkins.puppetlabs.com/view/Puppet%20FOSS/) + in [Puppet Strings](https://jenkins.puppetlabs.com/job/platform_puppet-strings_unit-ruby_master/) page.) * Watch the build until your changes have gone through green * Update the ticket status and target version. The target version field in @@ -143,7 +143,7 @@ First, the committer pulls down the branch using the `hub` gem. This tool automates the process of adding the remote repository and creating a local branch to track the remote branch. - $ hub checkout https://github.com/puppetlabs/puppetlabs-strings/pull/123 + $ hub checkout https://github.com/puppetlabs/puppet-strings/pull/123 Branch jeffmccune-pdoc-34_fix_foo_error set up to track remote branch pdoc-34-fix_foo_error from jeffmccune. Switched to a new branch 'jeffmccune-pdoc-34_fix_foo_error' @@ -178,7 +178,7 @@ Please note, the checklist should be complete at this point. It's helpful to mak sure your local branches are up to date to avoid one of the branches failing to fast forward while the other succeeds. - $ git push puppetlabs master:master + $ git push origin master:master That's it! The committer then updates the pull request, updates the issue in our issue tracker, and keeps an eye on the [build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed3c7c3..f366645 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,7 +68,7 @@ a ticket number. ## Submitting Changes -* Sign the [Contributor License Agreement](http://links.puppetlabs.com/cla). +* Sign the [Contributor License Agreement](http://links.puppet.com/cla). * Push your changes to a topic branch in your fork of the repository. * Submit a pull request to the repository in the puppetlabs organization. * Update your Jira ticket to mark that you have submitted code and are ready for it to be reviewed (Status: Ready for Merge). @@ -81,9 +81,9 @@ a ticket number. # Additional Resources -* [More information on contributing](http://links.puppetlabs.com/contribute-to-puppet) +* [More information on contributing](http://links.puppet.com/contribute-to-puppet) * [Bug tracker (Jira)](http://tickets.puppetlabs.com) -* [Contributor License Agreement](http://links.puppetlabs.com/cla) +* [Contributor License Agreement](http://links.puppet.com/cla) * [General GitHub documentation](http://help.github.com/) * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) * #puppet-dev IRC channel on freenode.org diff --git a/README.md b/README.md index 37acad8..f5e2ce2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Puppet Strings ============= -[![Build Status](https://travis-ci.org/puppetlabs/puppetlabs-strings.png?branch=master)](https://travis-ci.org/puppetlabs/puppetlabs-strings) [![Gem Version](https://badge.fury.io/rb/puppet-strings.svg)](https://badge.fury.io/rb/puppet-strings) +[![Build Status](https://travis-ci.org/puppetlabs/puppet-strings.png?branch=master)](https://travis-ci.org/puppetlabs/puppet-strings) [![Gem Version](https://badge.fury.io/rb/puppet-strings.svg)](https://badge.fury.io/rb/puppet-strings) A Puppet Face and plugin built on the [YARD Documentation Tool](http://yardoc.org/) and the Puppet 4 Parser. It is uses YARD and the Puppet Parser to generate HTML documentation about Puppet code and Puppet extensions written in Ruby. It will eventually replace the `puppet doc` command once feature parity has been achieved. @@ -13,12 +13,12 @@ A Puppet Face and plugin built on the [YARD Documentation Tool](http://yardoc.or | *Change log* | [CHANGELOG.md][changelog] | | *Contributing* | [CONTRIBUTING.md][contributing] and [COMMITTERS.md][committers]| -[repo]: https://github.com/puppetlabs/puppetlabs-strings +[repo]: https://github.com/puppetlabs/puppet-strings [JIRA]: https://tickets.puppetlabs.com/browse/PDOC -[LICENSE]: https://github.com/puppetlabs/puppetlabs-strings/blob/master/LICENSE -[changelog]: https://github.com/puppetlabs/puppetlabs-strings/blob/master/CHANGELOG.md -[contributing]: https://github.com/puppetlabs/puppetlabs-strings/blob/master/CONTRIBUTING.md -[committers]: https://github.com/puppetlabs/puppetlabs-strings/blob/master/COMMITTERS.md +[LICENSE]: https://github.com/puppetlabs/puppet-strings/blob/master/LICENSE +[changelog]: https://github.com/puppetlabs/puppet-strings/blob/master/CHANGELOG.md +[contributing]: https://github.com/puppetlabs/puppet-strings/blob/master/CONTRIBUTING.md +[committers]: https://github.com/puppetlabs/puppet-strings/blob/master/COMMITTERS.md Installation ------------ @@ -46,8 +46,6 @@ $ puppet resource package yard provider=gem Installing Strings Itself ------------------------- -**PLEASE NOTE** that Strings was previously distributed via the puppetlabs-strings module. This is no longer the preferred method of installation as the module will not longer receive updates. So even though there is still a module on the Puppet Forge, please use the RubyGem. - Strings can be installed using the [puppet-strings RubyGem](https://rubygems.org/gems/puppet-strings). To ensure it is installed in right place, it is best to install it using Puppet. For Puppet 4.x: @@ -91,7 +89,7 @@ It can also print the JSON to stdout: $ puppet strings yardoc some_manifest.pp --emit-json-stdout ``` -The schema for the JSON which Strings emits is [well documented](https://github.com/puppetlabs/puppetlabs-strings/blob/master/json_dom.md). +The schema for the JSON which Strings emits is [well documented](https://github.com/puppetlabs/puppet-strings/blob/master/json_dom.md). Processing is delegated to the `yardoc` tool so some options listed in `yard help doc` are available. However, Puppet Faces do not support passing arbitrary options through a face so these options must be specified in a `.yardopts` file. @@ -184,7 +182,7 @@ end Here are a few other good resources for getting started with documentation: - * [Module README Template](https://docs.puppetlabs.com/puppet/latest/reference/modules_documentation.html) + * [Module README Template](https://docs.puppet.com/puppet/latest/reference/modules_documentation.html) * [YARD Getting Started Guide](http://www.rubydoc.info/gems/yard/file/docs/GettingStarted.md) * [YARD Tags Overview](http://www.rubydoc.info/gems/yard/file/docs/Tags.md) @@ -196,7 +194,7 @@ This module is also available as a Gem and makes three rake tasks (`strings:gene In addition to generating the usual 'doc' directory of HTML documentation, the `strings:generate` rake task will also drop a strings.json file containing a JSON representation of the module into the directory the rake task was run from. ```ruby -gem 'puppet-strings', :git => 'https://github.com/puppetlabs/puppetlabs-strings.git' +gem 'puppet-strings', :git => 'https://github.com/puppetlabs/puppet-strings.git' ``` To use the rake tasks, `require puppet-strings/rake_tasks` in your `Rakefile`: @@ -231,7 +229,7 @@ This task aims to keep the `gh-pages` branch up to date with the current code an Developing and Contributing ----- -We love contributions from the community! If you'd like to contribute to the strings module, check out [CONTRIBUTING.md](https://github.com/puppetlabs/puppetlabs-strings/blob/master/CONTRIBUTING.md) to get information on the contribution process. +We love contributions from the community! If you'd like to contribute to the strings module, check out [CONTRIBUTING.md](https://github.com/puppetlabs/puppet-strings/blob/master/CONTRIBUTING.md) to get information on the contribution process. Running Specs ----- diff --git a/lib/puppet-strings/rake_tasks.rb b/lib/puppet-strings/rake_tasks.rb index eda4b5c..d35e402 100644 --- a/lib/puppet-strings/rake_tasks.rb +++ b/lib/puppet-strings/rake_tasks.rb @@ -1,19 +1,19 @@ require 'rake' require 'rake/tasklib' require 'puppet/face' -require 'puppet_x/puppetlabs/strings/util' +require 'puppet_x/puppet/strings/util' namespace :strings do desc 'Generate Puppet documentation with YARD.' task :generate do - PuppetX::PuppetLabs::Strings::Util.generate([ + PuppetX::Puppet::Strings::Util.generate([ {emit_json: 'strings.json'} ]) end desc 'Serve YARD documentation for modules.' task :serve do - PuppetX::PuppetLabs::Strings::Util.serve + PuppetX::Puppet::Strings::Util.serve end namespace :gh_pages do diff --git a/lib/puppet-strings/rake_tasks/generate.rb b/lib/puppet-strings/rake_tasks/generate.rb index e435c41..ba6bdbd 100644 --- a/lib/puppet-strings/rake_tasks/generate.rb +++ b/lib/puppet-strings/rake_tasks/generate.rb @@ -1,6 +1,6 @@ require 'rake' require 'rake/tasklib' -require 'puppet_x/puppetlabs/strings/util' +require 'puppet_x/puppet/strings/util' module PuppetStrings module RakeTasks @@ -8,7 +8,7 @@ module PuppetStrings # # @attr [String] name the name of the rake task. # @attr [Array] module_resourcefiles globs used to specify which files to document. - # Defaults to {PuppetX::PuppetLabs::Strings::Util::MODULE_SOURCEFILES} + # Defaults to {PuppetX::Puppet::Strings::Util::MODULE_SOURCEFILES} # @attr [Array] excludes a list of paths or patterns of files and directories to ignore. # @attr [Array, nil] paths list of paths to generate documentation for. # If this value is nil, uses the default paths for puppet strings. @@ -26,7 +26,7 @@ module PuppetStrings # mimic the current default behaviour. def initialize(*args, &task_block) @name = args.shift || 'strings:generate' - @module_sourcefiles = PuppetX::PuppetLabs::Strings::Util::MODULE_SOURCEFILES + @module_sourcefiles = PuppetX::Puppet::Strings::Util::MODULE_SOURCEFILES @paths = nil @options = {emit_json: 'strings.json'} @excludes = [] @@ -52,7 +52,7 @@ module PuppetStrings private # Converts all attributes and options to an arguments array that can be passed - # through to {PuppetX::PuppetLabs::Strings::Util #generate}. + # through to {PuppetX::Puppet::Strings::Util #generate}. # # If paths is not nil, we expand them with the module_sourcefiles patterns. def generate_task_args @@ -78,10 +78,10 @@ module PuppetStrings prefix_paths.map {|path| patterns.map {|p| "#{path}/**/#{p}" } }.flatten end - # call {PuppetX::PuppetLabs::Strings::Util #generate} + # call {PuppetX::Puppet::Strings::Util #generate} # @param [Array] args Arguments. Last element should be a Hash. def execute_task(args) - PuppetX::PuppetLabs::Strings::Util.generate(args) + PuppetX::Puppet::Strings::Util.generate(args) end end end diff --git a/lib/puppet/face/strings.rb b/lib/puppet/face/strings.rb index a695acb..72626ee 100644 --- a/lib/puppet/face/strings.rb +++ b/lib/puppet/face/strings.rb @@ -1,5 +1,5 @@ require 'puppet/face' -require 'puppet_x/puppetlabs/strings/yard/tags/directives' +require 'puppet_x/puppet/strings/yard/tags/directives' Puppet::Face.define(:strings, '0.0.1') do summary "Generate Puppet documentation with YARD." @@ -34,9 +34,9 @@ Puppet::Face.define(:strings, '0.0.1') do when_invoked do |*args| check_required_features - require 'puppet_x/puppetlabs/strings/util' + require 'puppet_x/puppet/strings/util' - PuppetX::PuppetLabs::Strings::Util.generate(args) + PuppetX::Puppet::Strings::Util.generate(args) # Puppet prints the return value of the action. The return value of this # action is that of the yardoc_actions invocation, which is the boolean @@ -56,9 +56,9 @@ Puppet::Face.define(:strings, '0.0.1') do when_invoked do |*args| check_required_features - require 'puppet_x/puppetlabs/strings/util' + require 'puppet_x/puppet/strings/util' - PuppetX::PuppetLabs::Strings::Util.serve(args) + PuppetX::Puppet::Strings::Util.serve(args) end end end diff --git a/lib/puppet_x/puppet/strings.rb b/lib/puppet_x/puppet/strings.rb new file mode 100644 index 0000000..96543e5 --- /dev/null +++ b/lib/puppet_x/puppet/strings.rb @@ -0,0 +1,64 @@ +require 'puppet' +require 'puppet/pops' +require 'puppet/util/docs' +require 'yard' + +module PuppetX +end + +# Nothing to see here except forward declarations. +module PuppetX::Puppet + module Strings + # This submodule contains bits that operate on the Pops module produced by + # the Future parser. + module Pops + require 'puppet_x/puppet/strings/pops/yard_statement' + require 'puppet_x/puppet/strings/pops/yard_transformer' + end + + # This submodule contains bits that interface with the YARD plugin system. + module YARD + require 'puppet_x/puppet/strings/yard/monkey_patches' + require 'puppet_x/puppet/strings/yard/parser' + + module Tags + require 'puppet_x/puppet/strings/yard/tags/directives' + end + + # This submodule contains code objects which are used to represent relevant + # aspects of puppet code in YARD's Registry + module CodeObjects + require 'puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object' + require 'puppet_x/puppet/strings/yard/code_objects/method_object' + require 'puppet_x/puppet/strings/yard/code_objects/defined_type_object' + require 'puppet_x/puppet/strings/yard/code_objects/host_class_object' + require 'puppet_x/puppet/strings/yard/code_objects/type_object' + require 'puppet_x/puppet/strings/yard/code_objects/provider_object' + end + + # This submodule contains handlers which are used to extract relevant data about + # puppet code from the ASTs produced by the Ruby and Puppet parsers + module Handlers + # This utility library contains some tools for working with Puppet docstrings + require 'puppet_x/puppet/strings/yard/handlers/base' + require 'puppet_x/puppet/strings/yard/handlers/defined_type_handler' + require 'puppet_x/puppet/strings/yard/handlers/host_class_handler' + require 'puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler' + require 'puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler' + require 'puppet_x/puppet/strings/yard/handlers/type_handler' + require 'puppet_x/puppet/strings/yard/handlers/provider_handler' + end + + ::YARD::Parser::SourceParser.register_parser_type(:puppet, + PuppetX::Puppet::Strings::YARD::PuppetParser, + ['pp']) + ::YARD::Handlers::Processor.register_handler_namespace(:puppet, + PuppetX::Puppet::Strings::YARD::Handlers) + + # FIXME: Might not be the best idea to have the template code on the Ruby + # LOAD_PATH as the contents of this directory really aren't library code. + ::YARD::Templates::Engine.register_template_path( + File.join(File.dirname(__FILE__), 'strings', 'yard', 'templates')) + end + end +end diff --git a/lib/puppet_x/puppetlabs/strings/actions.rb b/lib/puppet_x/puppet/strings/actions.rb similarity index 97% rename from lib/puppet_x/puppetlabs/strings/actions.rb rename to lib/puppet_x/puppet/strings/actions.rb index 50da802..dbbd87f 100644 --- a/lib/puppet_x/puppetlabs/strings/actions.rb +++ b/lib/puppet_x/puppet/strings/actions.rb @@ -1,6 +1,6 @@ -require 'puppet_x/puppetlabs/strings' +require 'puppet_x/puppet/strings' -class PuppetX::PuppetLabs::Strings::Actions +class PuppetX::Puppet::Strings::Actions # Creates a new instance of the Actions class by determining # whether or not debug and backtrace arguments should be sent diff --git a/lib/puppet_x/puppetlabs/strings/pops/yard_statement.rb b/lib/puppet_x/puppet/strings/pops/yard_statement.rb similarity index 97% rename from lib/puppet_x/puppetlabs/strings/pops/yard_statement.rb rename to lib/puppet_x/puppet/strings/pops/yard_statement.rb index f978d2c..f618bf3 100644 --- a/lib/puppet_x/puppetlabs/strings/pops/yard_statement.rb +++ b/lib/puppet_x/puppet/strings/pops/yard_statement.rb @@ -6,7 +6,7 @@ require 'ostruct' # FIXME: Inhertiting from OpenStruct is a bit of a hack. It allows attributes # to be declared as needed but in the long run understandibility of the code # would be improved by having a concrete model. -class PuppetX::PuppetLabs::Strings::Pops::YARDStatement < OpenStruct +class PuppetX::Puppet::Strings::Pops::YARDStatement < OpenStruct attr_reader :pops_obj, :comments def initialize(pops_obj) diff --git a/lib/puppet_x/puppetlabs/strings/pops/yard_transformer.rb b/lib/puppet_x/puppet/strings/pops/yard_transformer.rb similarity index 84% rename from lib/puppet_x/puppetlabs/strings/pops/yard_transformer.rb rename to lib/puppet_x/puppet/strings/pops/yard_transformer.rb index 0a47435..01cbd0d 100644 --- a/lib/puppet_x/puppetlabs/strings/pops/yard_transformer.rb +++ b/lib/puppet_x/puppet/strings/pops/yard_transformer.rb @@ -4,7 +4,7 @@ # # @note Currently, this class only extracts node, host class and type # definitions. -class PuppetX::PuppetLabs::Strings::Pops::YARDTransformer +class PuppetX::Puppet::Strings::Pops::YARDTransformer def initialize @transform_visitor = Puppet::Pops::Visitor.new(self, 'transform') end @@ -26,7 +26,7 @@ class PuppetX::PuppetLabs::Strings::Pops::YARDTransformer # Extract comments from type definitions and class definitions. Wrap them # into YARDStatement objects that provide an interface for YARD handlers. def transform_NamedDefinition(o) - obj = PuppetX::PuppetLabs::Strings::Pops::YARDStatement.new(o) + obj = PuppetX::Puppet::Strings::Pops::YARDStatement.new(o) obj.parameters = o.parameters.map do |p| param_tuple = [transform(p)] param_tuple << ( p.value.nil? ? nil : transform(p.value) ) @@ -37,7 +37,7 @@ class PuppetX::PuppetLabs::Strings::Pops::YARDTransformer # Catch-all visitor. def transform_Positioned(o) - PuppetX::PuppetLabs::Strings::Pops::YARDStatement.new(o) + PuppetX::Puppet::Strings::Pops::YARDStatement.new(o) end # nil in... nil out! diff --git a/lib/puppet_x/puppetlabs/strings/util.rb b/lib/puppet_x/puppet/strings/util.rb similarity index 85% rename from lib/puppet_x/puppetlabs/strings/util.rb rename to lib/puppet_x/puppet/strings/util.rb index 8d48c62..b99749c 100644 --- a/lib/puppet_x/puppetlabs/strings/util.rb +++ b/lib/puppet_x/puppet/strings/util.rb @@ -1,10 +1,10 @@ -require 'puppet_x/puppetlabs/strings/actions' +require 'puppet_x/puppet/strings/actions' -module PuppetX::PuppetLabs::Strings::Util +module PuppetX::Puppet::Strings::Util MODULE_SOURCEFILES = ['manifests/**/*.pp', 'lib/**/*.rb'] def self.generate(args = []) - yardoc_actions = PuppetX::PuppetLabs::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) + yardoc_actions = PuppetX::Puppet::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) # The last element of the argument array should be the options hash. # We don't have any options yet, so for now just pop the hash off and @@ -32,13 +32,13 @@ module PuppetX::PuppetLabs::Strings::Util #class YARD::Logger; def progress(*args); end; end YARD::Tags::Library.define_directive("puppet.type.param", :with_types_and_name, - PuppetX::PuppetLabs::Strings::YARD::Tags::PuppetTypeParameterDirective) + PuppetX::Puppet::Strings::YARD::Tags::PuppetTypeParameterDirective) yardoc_actions.generate_documentation(*yard_args) end def self.serve(args = []) - server_actions = PuppetX::PuppetLabs::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) + server_actions = PuppetX::Puppet::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) args.pop diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/defined_type_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb similarity index 84% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/defined_type_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb index e680157..5014908 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/code_objects/defined_type_object.rb +++ b/lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb @@ -1,6 +1,6 @@ require 'json' -class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::DefinedTypeObject < PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject +class PuppetX::Puppet::Strings::YARD::CodeObjects::DefinedTypeObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject # A list of parameters attached to this class. # @return [Array] attr_accessor :parameters diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/host_class_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb similarity index 77% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/host_class_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb index 0fc1c53..4234c15 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/code_objects/host_class_object.rb +++ b/lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::HostClassObject < PuppetX::PuppetLabs::Strings::YARD::CodeObjects::DefinedTypeObject +class PuppetX::Puppet::Strings::YARD::CodeObjects::HostClassObject < PuppetX::Puppet::Strings::YARD::CodeObjects::DefinedTypeObject # The {HostClassObject} that this class inherits from, if any. # @return [HostClassObject, Proxy, nil] attr_accessor :parent_class @@ -6,7 +6,7 @@ class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::HostClassObject < PuppetX # NOTE: `include_mods` is never used as it makes no sense for Puppet, but # this is called by `YARD::Registry` and it will pass a parameter. def inheritance_tree(include_mods = false) - if parent_class.is_a?(PuppetX::PuppetLabs::Strings::YARD::CodeObjects::HostClassObject) + if parent_class.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::HostClassObject) # Cool. We got a host class. Return self + parent inheritance tree. [self] + parent_class.inheritance_tree elsif parent_class.is_a?(YARD::CodeObjects::Proxy) diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/method_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/method_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/provider_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb similarity index 82% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/provider_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb index cf63c9d..d56e598 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/code_objects/provider_object.rb +++ b/lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::ProviderObject < PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject +class PuppetX::Puppet::Strings::YARD::CodeObjects::ProviderObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject # A list of parameters attached to this class. # @return [Array] attr_accessor :parameters diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/puppet_namespace_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb similarity index 93% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/puppet_namespace_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb index c3ba60b..6f6b3f1 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/code_objects/puppet_namespace_object.rb +++ b/lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject < YARD::CodeObjects::NamespaceObject +class PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject < YARD::CodeObjects::NamespaceObject attr_accessor :type_info # NOTE: `YARD::Registry#resolve` requires a method with this signature to diff --git a/lib/puppet_x/puppetlabs/strings/yard/code_objects/type_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb similarity index 91% rename from lib/puppet_x/puppetlabs/strings/yard/code_objects/type_object.rb rename to lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb index 513543f..b96b4a1 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/code_objects/type_object.rb +++ b/lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::CodeObjects::TypeObject < PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject +class PuppetX::Puppet::Strings::YARD::CodeObjects::TypeObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject # A list of parameters attached to this class. # @return [Array] attr_accessor :parameters diff --git a/lib/puppet_x/puppetlabs/strings/yard/core_ext/yard.rb b/lib/puppet_x/puppet/strings/yard/core_ext/yard.rb similarity index 97% rename from lib/puppet_x/puppetlabs/strings/yard/core_ext/yard.rb rename to lib/puppet_x/puppet/strings/yard/core_ext/yard.rb index d8accf2..fa8a0d4 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/core_ext/yard.rb +++ b/lib/puppet_x/puppet/strings/yard/core_ext/yard.rb @@ -1,6 +1,5 @@ require 'yard' - -require 'puppet_x/puppetlabs/strings' +require 'puppet_x/puppet/strings' # Patch the regular expression used to match namespaces # so it will allow namespace segments that begin with diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/base.rb b/lib/puppet_x/puppet/strings/yard/handlers/base.rb similarity index 56% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/base.rb rename to lib/puppet_x/puppet/strings/yard/handlers/base.rb index 0bd3e60..462f973 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/base.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/base.rb @@ -1,10 +1,10 @@ -require 'puppet_x/puppetlabs/strings/yard/core_ext/yard' +require 'puppet_x/puppet/strings/yard/core_ext/yard' -class PuppetX::PuppetLabs::Strings::YARD::Handlers::Base < ::YARD::Handlers::Base +class PuppetX::Puppet::Strings::YARD::Handlers::Base < ::YARD::Handlers::Base # Easy access to Pops model objects for handler matching. include Puppet::Pops::Model # Easy access to custom code objects from which documentation is generated. - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects + include PuppetX::Puppet::Strings::YARD::CodeObjects def self.handles?(statement) handlers.any? {|h| h == statement.type} diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/defined_type_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb similarity index 88% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/defined_type_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb index 78bff28..b54f5cb 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/defined_type_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::Handlers::DefinedTypeHandler < PuppetX::PuppetLabs::Strings::YARD::Handlers:: Base +class PuppetX::Puppet::Strings::YARD::Handlers::DefinedTypeHandler < PuppetX::Puppet::Strings::YARD::Handlers:: Base handles ResourceTypeDefinition process do diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/heredoc_helper.rb b/lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb similarity index 95% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/heredoc_helper.rb rename to lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb index 73fe2aa..072b469 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/heredoc_helper.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb @@ -47,11 +47,13 @@ class HereDocHelper # @param ele [YARD::Parser::Ruby::AstNode] # @return [String] def process_element(ele) - ele = ele.jump(:ident, :string_content) + ele = ele.jump(:ident, :symbol, :string_content) case ele.type when :ident ele.source + when :symbol + ele.source[1..-1] when :string_content source = ele.source if is_heredoc? source diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/host_class_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/host_class_handler.rb similarity index 94% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/host_class_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/host_class_handler.rb index 5eae337..16fed86 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/host_class_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/host_class_handler.rb @@ -1,4 +1,4 @@ -class PuppetX::PuppetLabs::Strings::YARD::Handlers::HostClassHandler < PuppetX::PuppetLabs::Strings::YARD::Handlers::Base +class PuppetX::Puppet::Strings::YARD::Handlers::HostClassHandler < PuppetX::Puppet::Strings::YARD::Handlers::Base handles HostClassDefinition process do diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/provider_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb similarity index 95% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/provider_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb index a22d2ae..8970086 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/provider_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb @@ -1,8 +1,8 @@ # Handles `dispatch` calls within a future parser function declaration. For # now, it just treats any docstring as an `@overlaod` tag and attaches the # overload to the parent function. -class PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetProviderHandler < YARD::Handlers::Ruby::Base - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects +class PuppetX::Puppet::Strings::YARD::Handlers::PuppetProviderHandler < YARD::Handlers::Ruby::Base + include PuppetX::Puppet::Strings::YARD::CodeObjects handles :command_call, :call diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_3x_function_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb similarity index 90% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_3x_function_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb index f55ad4f..183c120 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_3x_function_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb @@ -1,7 +1,7 @@ require File.join(File.dirname(__FILE__),'./heredoc_helper') -class PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet3xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects +class PuppetX::Puppet::Strings::YARD::Handlers::Puppet3xFunctionHandler < YARD::Handlers::Ruby::Base + include PuppetX::Puppet::Strings::YARD::CodeObjects handles method_call(:newfunction) diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_4x_function_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb similarity index 97% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_4x_function_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb index 298c8da..b301b6e 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/puppet_4x_function_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb @@ -1,8 +1,8 @@ # Handles `dispatch` calls within a future parser function declaration. For # now, it just treats any docstring as an `@overlaod` tag and attaches the # overload to the parent function. -class PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects +class PuppetX::Puppet::Strings::YARD::Handlers::Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base + include PuppetX::Puppet::Strings::YARD::CodeObjects handles method_call(:dispatch) @@ -19,7 +19,7 @@ class PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet4xFunctionHandler < YA end class Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects + include PuppetX::Puppet::Strings::YARD::CodeObjects handles method_call(:create_function) diff --git a/lib/puppet_x/puppetlabs/strings/yard/handlers/type_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/type_handler.rb similarity index 97% rename from lib/puppet_x/puppetlabs/strings/yard/handlers/type_handler.rb rename to lib/puppet_x/puppet/strings/yard/handlers/type_handler.rb index 346277b..19f326c 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/handlers/type_handler.rb +++ b/lib/puppet_x/puppet/strings/yard/handlers/type_handler.rb @@ -1,8 +1,8 @@ # Handles `dispatch` calls within a future parser function declaration. For # now, it just treats any docstring as an `@overlaod` tag and attaches the # overload to the parent function. -class PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetTypeHandler < YARD::Handlers::Ruby::Base - include PuppetX::PuppetLabs::Strings::YARD::CodeObjects +class PuppetX::Puppet::Strings::YARD::Handlers::PuppetTypeHandler < YARD::Handlers::Ruby::Base + include PuppetX::Puppet::Strings::YARD::CodeObjects handles :call @@ -130,7 +130,7 @@ class PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetTypeHandler < YARD::Ha elsif is_feature? node features << get_feature(node) elsif is_a_func_call_named? 'ensurable', node - # Someone could call the ensurable method and create an ensure + # Someone could call the ensurable method and create an ensure # property. If that happens, they it will be documented twice. Serves # them right. property_details << {:name => 'ensure', @@ -157,7 +157,7 @@ class PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetTypeHandler < YARD::Ha # See: - # https://docs.puppetlabs.com/guides/custom_types.html#namevar + # https://docs.puppet.com/guides/custom_types.html#namevar # node should be a parameter def is_namevar? node, param_name, type_name # Option 1: diff --git a/lib/puppet_x/puppetlabs/strings/yard/json_registry_store.rb b/lib/puppet_x/puppet/strings/yard/json_registry_store.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/json_registry_store.rb rename to lib/puppet_x/puppet/strings/yard/json_registry_store.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/monkey_patches.rb b/lib/puppet_x/puppet/strings/yard/monkey_patches.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/monkey_patches.rb rename to lib/puppet_x/puppet/strings/yard/monkey_patches.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/parser.rb b/lib/puppet_x/puppet/strings/yard/parser.rb similarity index 64% rename from lib/puppet_x/puppetlabs/strings/yard/parser.rb rename to lib/puppet_x/puppet/strings/yard/parser.rb index 630846d..b309a06 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/parser.rb +++ b/lib/puppet_x/puppet/strings/yard/parser.rb @@ -1,10 +1,10 @@ require 'yard' require 'puppet/pops' -require 'puppet_x/puppetlabs/strings' -require 'puppet_x/puppetlabs/strings//pops/yard_transformer' +require 'puppet_x/puppet/strings' +require 'puppet_x/puppet/strings//pops/yard_transformer' -class PuppetX::PuppetLabs::Strings::YARD::PuppetParser < YARD::Parser::Base +class PuppetX::Puppet::Strings::YARD::PuppetParser < YARD::Parser::Base attr_reader :file, :source def initialize(source, filename) @@ -12,7 +12,7 @@ class PuppetX::PuppetLabs::Strings::YARD::PuppetParser < YARD::Parser::Base @file = filename @parser = Puppet::Pops::Parser::Parser.new() - @transformer = PuppetX::PuppetLabs::Strings::Pops::YARDTransformer.new() + @transformer = PuppetX::Puppet::Strings::Pops::YARDTransformer.new() end def parse diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/docstring.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/parameter_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/definedtype/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_class.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_class.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb similarity index 94% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb index 7ab0dfe..ed09a8f 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb @@ -61,7 +61,7 @@ def namespace_list(opts = {}) if namespace_types.include? child.type if child.namespace.is_a?(CodeObjects::Proxy) name = child.path - elsif child.is_a?(PuppetX::PuppetLabs::Strings::YARD::CodeObjects::TypeObject) || child.is_a?(PuppetX::PuppetLabs::Strings::YARD::CodeObjects::ProviderObject) + elsif child.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::TypeObject) || child.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::ProviderObject) name = child.header_name else name = child.name diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/box_info.erb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/box_info.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/subclasses.erb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/html/subclasses.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/hostclass/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/html_helper.rb b/lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/html_helper.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/layout/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/layout/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/html/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb similarity index 91% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb index 94b383a..4ab00b6 100644 --- a/lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/setup.rb +++ b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb @@ -5,7 +5,7 @@ require File.join(File.dirname(__FILE__),'../template_helper') def init sections :header, [:method_signature, T('docstring'), :source] parents = YARD::Registry.all(:method).reject do |item| - item.name == object.name and item.namespace === PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject + item.name == object.name and item.namespace === PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject end if parents.length == 0 @template_helper = TemplateHelper.new diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/text/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/method_details/text/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/command_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/command_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/confine_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/confine_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/default_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/default_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/docstring.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/feature_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/feature_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/provider/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/box_info.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/method_summary.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/puppetnamespace/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/template_helper.rb b/lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/template_helper.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/docstring.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/header.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/parameter_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/parameter_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/provider_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/provider_details.erb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/html/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings/yard/templates/default/type/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb similarity index 100% rename from lib/puppet_x/puppetlabs/strings/yard/templates/default/type/setup.rb rename to lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb diff --git a/lib/puppet_x/puppetlabs/strings.rb b/lib/puppet_x/puppetlabs/strings.rb deleted file mode 100644 index 299af0b..0000000 --- a/lib/puppet_x/puppetlabs/strings.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'puppet' -require 'puppet/pops' -require 'puppet/util/docs' -require 'yard' - -module PuppetX -end - -# Nothing to see here except forward declarations. -module PuppetX::PuppetLabs - module Strings - # This submodule contains bits that operate on the Pops module produced by - # the Future parser. - module Pops - require 'puppet_x/puppetlabs/strings/pops/yard_statement' - require 'puppet_x/puppetlabs/strings/pops/yard_transformer' - end - - # This submodule contains bits that interface with the YARD plugin system. - module YARD - require 'puppet_x/puppetlabs/strings/yard/monkey_patches' - require 'puppet_x/puppetlabs/strings/yard/parser' - - module Tags - require 'puppet_x/puppetlabs/strings/yard/tags/directives' - end - - # This submodule contains code objects which are used to represent relevant - # aspects of puppet code in YARD's Registry - module CodeObjects - require 'puppet_x/puppetlabs/strings/yard/code_objects/puppet_namespace_object' - require 'puppet_x/puppetlabs/strings/yard/code_objects/method_object' - require 'puppet_x/puppetlabs/strings/yard/code_objects/defined_type_object' - require 'puppet_x/puppetlabs/strings/yard/code_objects/host_class_object' - require 'puppet_x/puppetlabs/strings/yard/code_objects/type_object' - require 'puppet_x/puppetlabs/strings/yard/code_objects/provider_object' - end - - # This submodule contains handlers which are used to extract relevant data about - # puppet code from the ASTs produced by the Ruby and Puppet parsers - module Handlers - # This utility library contains some tools for working with Puppet docstrings - require 'puppet_x/puppetlabs/strings/yard/handlers/base' - require 'puppet_x/puppetlabs/strings/yard/handlers/defined_type_handler' - require 'puppet_x/puppetlabs/strings/yard/handlers/host_class_handler' - require 'puppet_x/puppetlabs/strings/yard/handlers/puppet_3x_function_handler' - require 'puppet_x/puppetlabs/strings/yard/handlers/puppet_4x_function_handler' - require 'puppet_x/puppetlabs/strings/yard/handlers/type_handler' - require 'puppet_x/puppetlabs/strings/yard/handlers/provider_handler' - end - - ::YARD::Parser::SourceParser.register_parser_type(:puppet, - PuppetX::PuppetLabs::Strings::YARD::PuppetParser, - ['pp']) - ::YARD::Handlers::Processor.register_handler_namespace(:puppet, - PuppetX::PuppetLabs::Strings::YARD::Handlers) - - # FIXME: Might not be the best idea to have the template code on the Ruby - # LOAD_PATH as the contents of this directory really aren't library code. - ::YARD::Templates::Engine.register_template_path( - File.join(File.dirname(__FILE__), 'strings', 'yard', 'templates')) - end - end -end diff --git a/lib/puppet_x/puppetlabs/strings/yard/tags/directives.rb b/lib/puppet_x/puppetlabs/strings/yard/tags/directives.rb deleted file mode 100644 index 0b94793..0000000 --- a/lib/puppet_x/puppetlabs/strings/yard/tags/directives.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'puppet_x/puppetlabs/strings/yard/core_ext/yard' -# Creates a new code object based on the directive -class PuppetX::PuppetLabs::Strings::YARD::Tags::PuppetTypeParameterDirective < YARD::Tags::Directive - def call - return if object.nil? - object.parameters << ([tag.text, tag.types].flatten) - object.parameter_details << {:name => tag.name, :desc => tag.text, :exists? => true, :puppet_type => true} - end -end diff --git a/puppet-strings.gemspec b/puppet-strings.gemspec index 2a28e97..c0dfd7a 100644 --- a/puppet-strings.gemspec +++ b/puppet-strings.gemspec @@ -1,11 +1,11 @@ Gem::Specification.new do |s| s.name = 'puppet-strings' - s.author = 'Puppet Labs' + s.author = 'Puppet Inc.' s.version = '0.4.0' s.license = 'Apache-2.0' s.summary = 'Puppet documentation via YARD' - s.email = 'info@puppetlabs.com' - s.homepage = 'https://github.com/puppetlabs/puppetlabs-strings' + s.email = 'info@puppet.com' + s.homepage = 'https://github.com/puppetlabs/puppet-strings' s.description = s.summary s.extra_rdoc_files = [ diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index a751957..0546365 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,7 @@ require 'mocha' require 'puppet' require 'rspec' -require 'puppet_x/puppetlabs/strings' +require 'puppet_x/puppet/strings' RSpec.configure do |config| config.mock_with :mocha diff --git a/spec/unit/puppet_x/puppetlabs/strings/pops_spec.rb b/spec/unit/puppet_x/puppet/strings/pops_spec.rb similarity index 79% rename from spec/unit/puppet_x/puppetlabs/strings/pops_spec.rb rename to spec/unit/puppet_x/puppet/strings/pops_spec.rb index d8ac5f2..8a440e1 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/pops_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/pops_spec.rb @@ -1,13 +1,13 @@ require 'spec_helper' -require 'puppet_x/puppetlabs/strings/pops/yard_statement' +require 'puppet_x/puppet/strings/pops/yard_statement' -describe PuppetX::PuppetLabs::Strings::Pops do +describe PuppetX::Puppet::Strings::Pops do let(:parser) {Puppet::Pops::Parser::Parser.new()} describe "YARDstatement class" do let(:manifest) {"#hello world\nclass foo { }"} let(:model) {parser.parse_string(manifest).current.definitions.first} - let(:test_statement) {PuppetX::PuppetLabs::Strings::Pops::YARDStatement.new(model)} + let(:test_statement) {PuppetX::Puppet::Strings::Pops::YARDStatement.new(model)} describe "when creating a new instance of YARDStatement" do it "should extract comments from the source code" do @@ -19,13 +19,13 @@ describe PuppetX::PuppetLabs::Strings::Pops do describe "YARDTransfomer class" do let(:manifest) {"#hello world\nclass foo($bar) { }"} let(:manifest_default) {"#hello world\nclass foo($bar = 3) { }"} - let(:transformer) {PuppetX::PuppetLabs::Strings::Pops::YARDTransformer.new} + let(:transformer) {PuppetX::Puppet::Strings::Pops::YARDTransformer.new} describe "transform method" do it "should perform the correct transformation with parameter defaults" do model = parser.parse_string(manifest_default).current.definitions.first statements = transformer.transform(model) - expect(statements.parameters[0][0].class).to be(PuppetX::PuppetLabs::Strings::Pops::YARDStatement) + expect(statements.parameters[0][0].class).to be(PuppetX::Puppet::Strings::Pops::YARDStatement) end it "should perform the correct transofmration without parameter defaults" do diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/defined_type_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb similarity index 93% rename from spec/unit/puppet_x/puppetlabs/strings/yard/defined_type_handler_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb index 8ba38f7..6f3bd76 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/defined_type_handler_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -require 'puppet_x/puppetlabs/strings/yard/handlers/defined_type_handler' +require 'puppet_x/puppet/strings/yard/handlers/defined_type_handler' require 'strings_spec/parsing' -describe PuppetX::PuppetLabs::Strings::YARD::Handlers::DefinedTypeHandler do +describe PuppetX::Puppet::Strings::YARD::Handlers::DefinedTypeHandler do include StringsSpec::Parsing def the_definedtype() diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-differ/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match-with-types/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match-with-types/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test-param-names-match/lib/test.rb rename to spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/examples/test/manifests/init.pp b/spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp similarity index 100% rename from spec/unit/puppet_x/puppetlabs/strings/yard/examples/test/manifests/init.pp rename to spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/host_class_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb similarity index 95% rename from spec/unit/puppet_x/puppetlabs/strings/yard/host_class_handler_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb index c31e184..ea0959c 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/host_class_handler_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' require 'lib/strings_spec/module_helper' require 'puppet/face/strings' -require 'puppet_x/puppetlabs/strings/yard/handlers/host_class_handler' +require 'puppet_x/puppet/strings/yard/handlers/host_class_handler' require 'strings_spec/parsing' -describe PuppetX::PuppetLabs::Strings::YARD::Handlers::HostClassHandler do +describe PuppetX::Puppet::Strings::YARD::Handlers::HostClassHandler do include StringsSpec::Parsing def the_hostclass() diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/puppet_3x_function_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb similarity index 91% rename from spec/unit/puppet_x/puppetlabs/strings/yard/puppet_3x_function_handler_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb index 0b58605..d53c82d 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/puppet_3x_function_handler_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb @@ -1,8 +1,8 @@ require 'spec_helper' -require 'puppet_x/puppetlabs/strings/yard/handlers/puppet_3x_function_handler' +require 'puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler' require 'strings_spec/parsing' -describe PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet3xFunctionHandler do +describe PuppetX::Puppet::Strings::YARD::Handlers::Puppet3xFunctionHandler do include StringsSpec::Parsing def the_method() diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/puppet_4x_function_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb similarity index 97% rename from spec/unit/puppet_x/puppetlabs/strings/yard/puppet_4x_function_handler_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb index 6dcf9d4..e1b4e54 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/puppet_4x_function_handler_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb @@ -1,10 +1,10 @@ require 'spec_helper' require 'lib/strings_spec/module_helper' -require 'puppet_x/puppetlabs/strings/yard/handlers/puppet_4x_function_handler' +require 'puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler' require 'puppet/face/strings' require 'strings_spec/parsing' -describe PuppetX::PuppetLabs::Strings::YARD::Handlers::Puppet4xFunctionHandler do +describe PuppetX::Puppet::Strings::YARD::Handlers::Puppet4xFunctionHandler do include StringsSpec::Parsing def the_method() diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/template_helper_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb similarity index 84% rename from spec/unit/puppet_x/puppetlabs/strings/yard/template_helper_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb index 6772d7d..f6153a8 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/template_helper_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -require 'puppet_x/puppetlabs/strings/yard/templates/default/template_helper' -require 'puppet_x/puppetlabs/strings/yard/code_objects/puppet_namespace_object' +require 'puppet_x/puppet/strings/yard/templates/default/template_helper' +require 'puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object' require 'strings_spec/parsing' describe TemplateHelper do @@ -11,7 +11,7 @@ describe TemplateHelper do # nothing is printed tag0 = YARD::Tags::Tag.new(:param, 'a_parameter') tag0.name = 'a_parameter' - obj0 = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') + obj0 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') obj0.add_tag tag0 obj0.parameters = [['a_parameter']] expect { th.check_parameters_match_docs obj0 }.to output("").to_stderr_from_any_process @@ -28,7 +28,7 @@ describe TemplateHelper do # formed, print out the warning with no location data tag1 = YARD::Tags::Tag.new(:param, 'aa_parameter') tag1.name = 'aa_parameter' - obj1 = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') + obj1 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') obj1.add_tag tag1 obj1.parameters = [['b_parameter']] expect { th.check_parameters_match_docs obj1 }.to output("[warn]: The parameter aa_parameter is documented, but doesn't exist in\n your code. Sorry, the file and line number could not be determined.\n").to_stderr_from_any_process @@ -45,7 +45,7 @@ describe TemplateHelper do # formed, print out the warning with no location data tag2 = YARD::Tags::Tag.new(:param, 'aaa_parameter') tag2.name = 'aaa_parameter' - obj2 = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') + obj2 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') obj2.files = [['some_file.pp', 42]] obj2.add_tag tag2 obj2.parameters = [['b_parameter']] @@ -61,7 +61,7 @@ describe TemplateHelper do " code. The arg1\n parameter is declared as types [\"Integer\"] in the " + "docstring,\n but the code specifies the types [\"Optional[String]\"]" + "\n in the file test near line 0.\n" - object = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') + object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') object.files = [['test', 0]] object.type_info = [{ 'arg0' => 'Variant[String,Array[String]]', @@ -82,7 +82,7 @@ describe TemplateHelper do end it "should not issue a warning if the parameter types do match the docstring in dispatch method" do - object = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') + object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') object.files = [['test', 0]] object.type_info = [{ 'arg0' => 'Variant[String,Array[String]]', @@ -103,7 +103,7 @@ describe TemplateHelper do end it "should not issue a warning if the types in the docstring in dispatch method are assignable to parameter types" do - object = PuppetX::PuppetLabs::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') + object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') object.files = [['test', 0]] object.type_info = [{ 'arg0' => 'Variant[String,Array[String]]', diff --git a/spec/unit/puppet_x/puppetlabs/strings/yard/type_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb similarity index 92% rename from spec/unit/puppet_x/puppetlabs/strings/yard/type_handler_spec.rb rename to spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb index 338ce5c..72c53b1 100644 --- a/spec/unit/puppet_x/puppetlabs/strings/yard/type_handler_spec.rb +++ b/spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb @@ -1,9 +1,9 @@ require 'spec_helper' -require 'puppet_x/puppetlabs/strings/yard/handlers/type_handler' +require 'puppet_x/puppet/strings/yard/handlers/type_handler' require 'strings_spec/parsing' -describe PuppetX::PuppetLabs::Strings::YARD::Handlers::PuppetTypeHandler do +describe PuppetX::Puppet::Strings::YARD::Handlers::PuppetTypeHandler do include StringsSpec::Parsing def the_type() From ea9dd0c8462f4fa6c69b28be6e40b314c5754ae2 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Fri, 9 Sep 2016 13:44:05 -0700 Subject: [PATCH 03/15] (PDOC-63) Delete the old implementation. This commit deletes the old implementation to assist in cleaner code reviews of the upcoming reimplementation. This commit also moves YARD to version 0.9.5 and lays down a bare bones implementation of Puppet Strings that currently does nothing. --- .rubocop.yml | 2 +- .yardopts | 4 +- Gemfile | 2 +- README.md | 22 +- lib/puppet-strings.rb | 56 ++++ lib/puppet-strings/rake_tasks.rb | 58 ---- lib/puppet-strings/rake_tasks/generate.rb | 88 ------ lib/puppet/application/strings.rb | 1 + lib/puppet/face/strings.rb | 121 ++++--- lib/puppet_x/puppet/strings.rb | 64 ---- lib/puppet_x/puppet/strings/actions.rb | 92 ------ .../puppet/strings/pops/yard_statement.rb | 79 ----- .../puppet/strings/pops/yard_transformer.rb | 47 --- lib/puppet_x/puppet/strings/util.rb | 65 ---- .../yard/code_objects/defined_type_object.rb | 33 -- .../yard/code_objects/host_class_object.rb | 22 -- .../yard/code_objects/method_object.rb | 62 ---- .../yard/code_objects/provider_object.rb | 24 -- .../code_objects/puppet_namespace_object.rb | 48 --- .../strings/yard/code_objects/type_object.rb | 42 --- .../puppet/strings/yard/core_ext/yard.rb | 39 --- .../puppet/strings/yard/handlers/base.rb | 13 - .../yard/handlers/defined_type_handler.rb | 31 -- .../strings/yard/handlers/heredoc_helper.rb | 82 ----- .../yard/handlers/host_class_handler.rb | 55 ---- .../strings/yard/handlers/provider_handler.rb | 96 ------ .../handlers/puppet_3x_function_handler.rb | 54 ---- .../handlers/puppet_4x_function_handler.rb | 234 -------------- .../strings/yard/handlers/type_handler.rb | 295 ------------------ .../strings/yard/json_registry_store.rb | 85 ----- .../puppet/strings/yard/monkey_patches.rb | 68 ---- lib/puppet_x/puppet/strings/yard/parser.rb | 30 -- .../default/definedtype/html/docstring.erb | 34 -- .../default/definedtype/html/header.erb | 5 - .../definedtype/html/parameter_details.erb | 6 - .../default/definedtype/html/setup.rb | 1 - .../templates/default/definedtype/setup.rb | 49 --- .../default/fulldoc/html/full_list_class.erb | 2 - .../html/full_list_puppet_manifest.erb | 1 - .../fulldoc/html/full_list_puppet_plugin.erb | 21 -- .../html/full_list_puppet_provider.erb | 1 - .../fulldoc/html/full_list_puppet_type.erb | 1 - .../templates/default/fulldoc/html/setup.rb | 82 ----- .../default/hostclass/html/box_info.erb | 22 -- .../templates/default/hostclass/html/setup.rb | 1 - .../default/hostclass/html/subclasses.erb | 4 - .../yard/templates/default/hostclass/setup.rb | 21 -- .../yard/templates/default/html_helper.rb | 139 --------- .../templates/default/layout/html/setup.rb | 18 -- .../default/method_details/html/header.erb | 17 - .../templates/default/method_details/setup.rb | 21 -- .../default/method_details/text/header.erb | 2 - .../default/provider/html/command_details.erb | 8 - .../default/provider/html/confine_details.erb | 10 - .../default/provider/html/default_details.erb | 10 - .../default/provider/html/docstring.erb | 34 -- .../default/provider/html/feature_details.erb | 10 - .../default/provider/html/header.erb | 5 - .../templates/default/provider/html/setup.rb | 1 - .../yard/templates/default/provider/setup.rb | 50 --- .../default/puppetnamespace/html/box_info.erb | 11 - .../default/puppetnamespace/html/header.erb | 5 - .../html/method_details_list.erb | 53 ---- .../puppetnamespace/html/method_summary.erb | 20 -- .../default/puppetnamespace/html/setup.rb | 1 - .../default/puppetnamespace/setup.rb | 91 ------ .../yard/templates/default/template_helper.rb | 192 ------------ .../templates/default/type/html/docstring.erb | 34 -- .../templates/default/type/html/header.erb | 5 - .../default/type/html/parameter_details.erb | 12 - .../default/type/html/provider_details.erb | 10 - .../yard/templates/default/type/html/setup.rb | 1 - .../yard/templates/default/type/setup.rb | 55 ---- puppet-strings.gemspec | 2 +- spec/lib/strings_spec/module_helper.rb | 20 -- spec/lib/strings_spec/parsing.rb | 42 --- spec/spec_helper.rb | 2 +- .../test/lib/puppet/functions/4x_function.rb | 5 - .../lib/puppet/parser/functions/function3x.rb | 3 - .../puppet/examples/test/manifests/init.pp | 27 -- .../test/manifests/triple_nested_classes.pp | 27 -- spec/unit/puppet/examples/test/metadata.json | 6 - spec/unit/puppet/face_spec.rb | 132 -------- .../unit/puppet_x/puppet/strings/pops_spec.rb | 38 --- .../strings/yard/defined_type_handler_spec.rb | 74 ----- .../lib/test.rb | 18 -- .../lib/test.rb | 7 - .../test-param-names-differ/lib/test.rb | 7 - .../lib/test.rb | 11 - .../lib/test.rb | 7 - .../test-param-names-match/lib/test.rb | 7 - .../yard/examples/test/manifests/init.pp | 7 - .../strings/yard/host_class_handler_spec.rb | 93 ------ .../yard/puppet_3x_function_handler_spec.rb | 63 ---- .../yard/puppet_4x_function_handler_spec.rb | 150 --------- .../strings/yard/template_helper_spec.rb | 125 -------- .../puppet/strings/yard/type_handler_spec.rb | 67 ---- 97 files changed, 158 insertions(+), 3862 deletions(-) create mode 100644 lib/puppet-strings.rb delete mode 100644 lib/puppet-strings/rake_tasks.rb delete mode 100644 lib/puppet-strings/rake_tasks/generate.rb delete mode 100644 lib/puppet_x/puppet/strings.rb delete mode 100644 lib/puppet_x/puppet/strings/actions.rb delete mode 100644 lib/puppet_x/puppet/strings/pops/yard_statement.rb delete mode 100644 lib/puppet_x/puppet/strings/pops/yard_transformer.rb delete mode 100644 lib/puppet_x/puppet/strings/util.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/core_ext/yard.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/base.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/host_class_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/handlers/type_handler.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/json_registry_store.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/monkey_patches.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/parser.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb delete mode 100644 lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb delete mode 100644 spec/lib/strings_spec/module_helper.rb delete mode 100644 spec/lib/strings_spec/parsing.rb delete mode 100644 spec/unit/puppet/examples/test/lib/puppet/functions/4x_function.rb delete mode 100644 spec/unit/puppet/examples/test/lib/puppet/parser/functions/function3x.rb delete mode 100644 spec/unit/puppet/examples/test/manifests/init.pp delete mode 100644 spec/unit/puppet/examples/test/manifests/triple_nested_classes.pp delete mode 100644 spec/unit/puppet/examples/test/metadata.json delete mode 100644 spec/unit/puppet/face_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/pops_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb delete mode 100644 spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index dd88b39..1a14db7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,7 +2,7 @@ AllCops: Exclude: # Ignore HTML related things - '**/*.erb' - - 'lib/puppetx/puppet/strings/yard/templates/**/*' + - 'lib/puppet-strings/yard/templates/**/*' Lint/ConditionPosition: Enabled: true diff --git a/.yardopts b/.yardopts index bddb273..a0729ad 100644 --- a/.yardopts +++ b/.yardopts @@ -1,2 +1,2 @@ ---exclude lib/puppetx/puppet/strings/yard/templates/ ---exclude lib/puppetx/puppet/strings/yard/code_objects/host_class_object.rb +--exclude lib/puppet-strings/yard/templates/ +--no-private diff --git a/Gemfile b/Gemfile index bb48c59..756f11d 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ gemspec gem 'rgen' gem 'redcarpet' -gem "yard", "~> 0.8.7" +gem 'yard', '~> 0.9.5' puppetversion = ENV['PUPPET_VERSION'] diff --git a/README.md b/README.md index f5e2ce2..d087e6b 100644 --- a/README.md +++ b/README.md @@ -68,30 +68,36 @@ $ cd /path/to/module $ puppet strings ``` -This processes `README` and all puppet and ruby files under `manifests/` -and `lib/`. +This processes `README` and all Puppet and Ruby source files under the `./manifests/`, `./functions/`, and `./lib/` +directories by default. To document specific files: ``` -$ puppet strings some_manifest.pp [another_if_you_feel_like_it.rb] +$ puppet strings first.pp second.pp ... +``` + +To document specific directories: + +``` +$ puppet strings 'modules/foo/lib/**/*.rb' 'modules/foo/manifests/**/*.pp' 'modules/foo/functions/**/*.pp' ... ``` Strings can also emit the generated documentation as JSON: ``` -$ puppet strings yardoc some_manifest.pp --emit-json documentation.json +$ puppet strings generate manifest.pp --emit-json documentation.json ``` It can also print the JSON to stdout: ``` -$ puppet strings yardoc some_manifest.pp --emit-json-stdout +$ puppet strings generate manifest.pp --emit-json-stdout ``` -The schema for the JSON which Strings emits is [well documented](https://github.com/puppetlabs/puppet-strings/blob/master/json_dom.md). +The schema for the JSON which Strings emits is [documented here](https://github.com/puppetlabs/puppet-strings/blob/master/json_dom.md). -Processing is delegated to the `yardoc` tool so some options listed in `yard help doc` are available. However, Puppet Faces do not support passing arbitrary options through a face so these options must be specified in a `.yardopts` file. +Processing is delegated to the `yard` tool so some options listed in `yard help doc` are available. However, Puppet Faces do not support passing arbitrary options through a face so these options must be specified in a `.yardopts` file. In addition to generating a directory full of HTML, you can also serve up documentation for all your modules using the `server` action: @@ -155,7 +161,7 @@ class example ( ### Types and Providers Strings will automatically extract the `@doc` provider docstring and any `desc` parameter/property docstrings. -Sometimes however, Puppet types use metaprogramming to create parameters and methods automatically. In those cases Strings will not be able to document them automatically (Strings doesn't execute the code that would generate those parameters), so you will need to provide hints on how to document your code. To document a parameter which is automatically created you must use the special directive `@!puppet.type.param` which may take types, the parameter name, and a description. +Sometimes however, Puppet types use metaprogramming to create parameters and methods automatically. In those cases Strings will not be able to document them automatically (Strings doesn't execute the code that would generate those parameters), so you will need to provide hints on how to document your code. To document a parameter which is automatically created you must use the special directive `@!puppet.type.param` or `@!puppet.type.property` which may take types, the parameter or property name, and a description. ```ruby # @!puppet.type.param my_parameter This parameter needs to be explicitly diff --git a/lib/puppet-strings.rb b/lib/puppet-strings.rb new file mode 100644 index 0000000..0a61787 --- /dev/null +++ b/lib/puppet-strings.rb @@ -0,0 +1,56 @@ +# The root module for Puppet Strings. +module PuppetStrings + # The glob patterns used to search for files to document. + DEFAULT_SEARCH_PATTERNS = %w( + manifests/**/*.pp + functions/**/*.pp + types/**/*.pp + lib/**/*.rb + ).freeze + + # Generates documentation. + # @param [Array] search_patterns The search patterns (e.g. manifests/**/*.pp) to look for files. + # @param [Hash] options The options hash. + # @option options [Boolean] :debug Enable YARD debug output. + # @option options [Boolean] :backtrace Enable YARD backtraces. + # @option options [String] :markup The YARD markup format to use (defaults to 'markdown'). + # @option options [String] :json Enables JSON output to the given file. If the file is nil, STDOUT is used. + # @option options [Array] :yard_args The arguments to pass to yard. + # @return [void] + def self.generate(search_patterns = DEFAULT_SEARCH_PATTERNS, options = {}) + # Format the arguments to YARD + args = ['doc'] + args << '--debug' if options[:debug] + args << '--backtrace' if options[:backtrace] + args << "-m#{options[:markup] || 'markdown'}" + + render_as_json = options.key? :json + json_file = nil + if render_as_json + json_file = options[:json] + # Disable output and prevent stats/progress when writing to STDOUT + args << '-n' + args << '-q' unless json_file + args << '--no-stats' unless json_file + args << '--no-progress' unless json_file + end + + yard_args = options[:yard_args] + args += yard_args if yard_args + args += search_patterns + + # Run YARD + YARD::CLI::Yardoc.run(*args) + + # If outputting JSON, render the output + if render_as_json + # TODO: implement + end + end + + # Runs the YARD documentation server. + # @param [Array] args The arguments to YARD. + def self.run_server(*args) + YARD::CLI::Server.run(*args) + end +end diff --git a/lib/puppet-strings/rake_tasks.rb b/lib/puppet-strings/rake_tasks.rb deleted file mode 100644 index d35e402..0000000 --- a/lib/puppet-strings/rake_tasks.rb +++ /dev/null @@ -1,58 +0,0 @@ -require 'rake' -require 'rake/tasklib' -require 'puppet/face' -require 'puppet_x/puppet/strings/util' - -namespace :strings do - desc 'Generate Puppet documentation with YARD.' - task :generate do - PuppetX::Puppet::Strings::Util.generate([ - {emit_json: 'strings.json'} - ]) - end - - desc 'Serve YARD documentation for modules.' - task :serve do - PuppetX::Puppet::Strings::Util.serve - end - - namespace :gh_pages do - git_uri = `git config --get remote.origin.url`.strip - - desc "Checkout the gh-pages branch for doc generation." - task :checkout do - if Dir.exist?('doc') - fail "The 'doc' directory (#{File.expand_path('doc')}) is not a Git repository! Remove it and run the Rake task again." unless Dir.exist?('doc/.git') - Dir.chdir('doc') do - system 'git checkout gh-pages' - system 'git reset --hard origin/gh-pages' - system 'git pull origin gh-pages' - end - else - Dir.mkdir('doc') - Dir.chdir('doc') do - system 'git init' - system "git remote add origin #{git_uri}" - system 'git pull' - system 'git checkout -b gh-pages' - end - end - end - - desc "Push new docs to GitHub." - task :push do - Dir.chdir('doc') do - system 'git add .' - system "git commit -m '[strings] Generated Documentation Update'" - system 'git push origin gh-pages -f' - end - end - - desc "Run checkout, generate, and push tasks." - task :update => [ - :checkout, - :'strings:generate', - :push, - ] - end -end diff --git a/lib/puppet-strings/rake_tasks/generate.rb b/lib/puppet-strings/rake_tasks/generate.rb deleted file mode 100644 index ba6bdbd..0000000 --- a/lib/puppet-strings/rake_tasks/generate.rb +++ /dev/null @@ -1,88 +0,0 @@ -require 'rake' -require 'rake/tasklib' -require 'puppet_x/puppet/strings/util' - -module PuppetStrings - module RakeTasks - # A configurable rake task to generate documentation using puppet-strings. - # - # @attr [String] name the name of the rake task. - # @attr [Array] module_resourcefiles globs used to specify which files to document. - # Defaults to {PuppetX::Puppet::Strings::Util::MODULE_SOURCEFILES} - # @attr [Array] excludes a list of paths or patterns of files and directories to ignore. - # @attr [Array, nil] paths list of paths to generate documentation for. - # If this value is nil, uses the default paths for puppet strings. - # @attr [Hash] options a hash with options passed through to yardoc. - class Generate < ::Rake::TaskLib - attr_accessor :name - attr_accessor :module_resourcefiles - attr_accessor :paths - attr_accessor :excludes - attr_accessor :options - - # Creates a new instance of the Generate Rake task. - # Defaults the name to 'strings:generate which overrides - # the namespaced generates task. Also default other attributes to - # mimic the current default behaviour. - def initialize(*args, &task_block) - @name = args.shift || 'strings:generate' - @module_sourcefiles = PuppetX::Puppet::Strings::Util::MODULE_SOURCEFILES - @paths = nil - @options = {emit_json: 'strings.json'} - @excludes = [] - define(args, &task_block) - end - - # Creates the actual rake task after calling the task_block. - # - # @param [Array] args arguments passed to the rake task. - # @param [Proc] task_block block to configure the task. - # @yield [self, args] configure this rake task. - def define(args, &task_block) - Rake::Task[@name].clear if Rake::Task.task_defined?(@name) - yield(*[self, args].slice(0, task_block.arity)) if task_block - - - desc 'Generate Puppet documentation with YARD.' unless ::Rake.application.last_description - task @name do - execute_task(generate_task_args) - end - end - - private - - # Converts all attributes and options to an arguments array that can be passed - # through to {PuppetX::Puppet::Strings::Util #generate}. - # - # If paths is not nil, we expand them with the module_sourcefiles patterns. - def generate_task_args - @paths = [*@paths] unless @paths.nil? - @module_sourcefiles = [*@module_sourcefiles] - @excludes = [*@excludes] - - exclude_args = @excludes.map {|x| ["--exclude", x]}.flatten - pattern_args = @paths.nil? ? [] : expand_paths(@paths, @module_sourcefiles) - - exclude_args + pattern_args + [@options] - end - - # Combine each prefix_path with each pattern with '/**/' glue. - # - # @example - # expand_paths(['a','b'], ['*.rb','*.pp']) - # => ["a/**/*.rb", "a/**/*.pp", "b/**/*.rb", "b/**/*.pp"] - # - # @param [Array] prefix_paths an array with paths - # @param [Array] patterns an array with patterns. - def expand_paths(prefix_paths, patterns) - prefix_paths.map {|path| patterns.map {|p| "#{path}/**/#{p}" } }.flatten - end - - # call {PuppetX::Puppet::Strings::Util #generate} - # @param [Array] args Arguments. Last element should be a Hash. - def execute_task(args) - PuppetX::Puppet::Strings::Util.generate(args) - end - end - end -end diff --git a/lib/puppet/application/strings.rb b/lib/puppet/application/strings.rb index 119b003..5a4f06d 100644 --- a/lib/puppet/application/strings.rb +++ b/lib/puppet/application/strings.rb @@ -1,4 +1,5 @@ require 'puppet/application/face_base' +# Implements the 'puppet strings' application. class Puppet::Application::Strings < Puppet::Application::FaceBase end diff --git a/lib/puppet/face/strings.rb b/lib/puppet/face/strings.rb index 72626ee..ba441ed 100644 --- a/lib/puppet/face/strings.rb +++ b/lib/puppet/face/strings.rb @@ -1,64 +1,105 @@ require 'puppet/face' -require 'puppet_x/puppet/strings/yard/tags/directives' +# Implements the 'puppet strings' interface. Puppet::Face.define(:strings, '0.0.1') do - summary "Generate Puppet documentation with YARD." + summary 'Generate Puppet documentation with YARD.' - # Ensures that the user has the needed features to use puppet strings - def check_required_features - unless Puppet.features.yard? - raise RuntimeError, "The 'yard' gem must be installed in order to use this face." - end - - unless Puppet.features.rgen? - raise RuntimeError, "The 'rgen' gem must be installed in order to use this face." - end - - if RUBY_VERSION.match(/^1\.8/) - raise RuntimeError, "This face requires Ruby 1.9 or greater." - end - end - - action(:yardoc) do + action(:generate) do default - option "--emit-json-stdout" do - summary "Print json representation of the documentation to stdout" + option '--emit-json-stdout' do + summary 'Print JSON representation of the documentation to stdout.' end - option "--emit-json FILE" do - summary "Write json representation of the documentation to FILE" + option '--emit-json FILE' do + summary 'Write JSON representation of the documentation to the given file.' + end + option '--markup FORMAT' do + summary "The markup format to use for docstring text (defaults to 'markdown')." end - summary "Generate YARD documentation from files." - arguments "[manifest_file.pp ...]" + summary 'Generate documentation from files.' + arguments '[[search_pattern] ...]' when_invoked do |*args| check_required_features - require 'puppet_x/puppet/strings/util' + require 'puppet-strings' - PuppetX::Puppet::Strings::Util.generate(args) - - # Puppet prints the return value of the action. The return value of this - # action is that of the yardoc_actions invocation, which is the boolean - # "true". This clutters the statistics yard prints, so instead return the - # empty string. Note an extra newline will also be printed. - "" + PuppetStrings::generate( + args.count > 1 ? args[0..-2] : PuppetStrings::DEFAULT_SEARCH_PATTERNS, + build_generate_options(args.last) + ) + nil end end - # NOTE: Modeled after the `yard gems` command which builds doc indicies - # (.yardoc directories) for Ruby Gems. Currently lacks the fine-grained - # control over where these indicies are created and just dumps them in the - # module roots. - action(:server) do - summary "Serve YARD documentation for modules." + option '--markup FORMAT' do + summary "The markup format to use for docstring text (defaults to 'markdown')." + end + + summary 'Runs a local documentation server for the modules in the current Puppet environment.' + arguments '[[module_name] ...]' when_invoked do |*args| check_required_features - require 'puppet_x/puppet/strings/util' + require 'puppet-strings' - PuppetX::Puppet::Strings::Util.serve(args) + modules = args.count > 1 ? args[0..-2] : [] + + # Generate documentation for all (or the given) modules + module_docs = [] + environment = Puppet.lookup(:current_environment) + environment.modules.each do |mod| + next unless modules.empty? || modules.include?(mod.name) + db = File.join(mod.path, '.yardoc') + patterns = PuppetStrings::DEFAULT_SEARCH_PATTERNS.map do |p| + File.join(mod.path, p) + end + puts "Generating documentation for Puppet module '#{mod.name}'." + PuppetStrings.generate(patterns, build_generate_options(args.last, '--db', db)) + + # Clear the registry so that the next call to generate has a clean database + YARD::Registry.clear + + module_docs << mod.name + module_docs << db + end + + if module_docs.empty? + puts 'No Puppet modules were found to serve documentation for.' + return + end + puts 'Starting YARD documentation server.' + PuppetStrings::run_server('-m', *module_docs) + nil end end + + # Checks that the required features are installed. + # @return [void] + def check_required_features + raise RuntimeError, "The 'yard' gem must be installed in order to use this face." unless Puppet.features.yard? + raise RuntimeError, "The 'rgen' gem must be installed in order to use this face." unless Puppet.features.rgen? + raise RuntimeError, 'This face requires Ruby 1.9 or greater.' if RUBY_VERSION.match(/^1\.8/) + end + + # Builds the options to PuppetStrings.generate. + # @param [Hash] options The Puppet face options hash. + # @param [Array] yard_args The additional arguments to pass to YARD. + # @return [Hash] Returns the PuppetStrings.generate options hash. + def build_generate_options(options = nil, *yard_args) + generate_options = {} + generate_options[:debug] = Puppet[:debug] + generate_options[:backtrace] = Puppet[:trace] + generate_options[:yard_args] = yard_args unless yard_args.empty? + + if options + markup = options[:markup] + generate_options[:markup] = markup if markup + json_file = options[:emit_json] + generate_options[:json] = json_file if json_file + generate_options[:json] = nil if options[:emit_json_stdout] + end + generate_options + end end diff --git a/lib/puppet_x/puppet/strings.rb b/lib/puppet_x/puppet/strings.rb deleted file mode 100644 index 96543e5..0000000 --- a/lib/puppet_x/puppet/strings.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'puppet' -require 'puppet/pops' -require 'puppet/util/docs' -require 'yard' - -module PuppetX -end - -# Nothing to see here except forward declarations. -module PuppetX::Puppet - module Strings - # This submodule contains bits that operate on the Pops module produced by - # the Future parser. - module Pops - require 'puppet_x/puppet/strings/pops/yard_statement' - require 'puppet_x/puppet/strings/pops/yard_transformer' - end - - # This submodule contains bits that interface with the YARD plugin system. - module YARD - require 'puppet_x/puppet/strings/yard/monkey_patches' - require 'puppet_x/puppet/strings/yard/parser' - - module Tags - require 'puppet_x/puppet/strings/yard/tags/directives' - end - - # This submodule contains code objects which are used to represent relevant - # aspects of puppet code in YARD's Registry - module CodeObjects - require 'puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object' - require 'puppet_x/puppet/strings/yard/code_objects/method_object' - require 'puppet_x/puppet/strings/yard/code_objects/defined_type_object' - require 'puppet_x/puppet/strings/yard/code_objects/host_class_object' - require 'puppet_x/puppet/strings/yard/code_objects/type_object' - require 'puppet_x/puppet/strings/yard/code_objects/provider_object' - end - - # This submodule contains handlers which are used to extract relevant data about - # puppet code from the ASTs produced by the Ruby and Puppet parsers - module Handlers - # This utility library contains some tools for working with Puppet docstrings - require 'puppet_x/puppet/strings/yard/handlers/base' - require 'puppet_x/puppet/strings/yard/handlers/defined_type_handler' - require 'puppet_x/puppet/strings/yard/handlers/host_class_handler' - require 'puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler' - require 'puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler' - require 'puppet_x/puppet/strings/yard/handlers/type_handler' - require 'puppet_x/puppet/strings/yard/handlers/provider_handler' - end - - ::YARD::Parser::SourceParser.register_parser_type(:puppet, - PuppetX::Puppet::Strings::YARD::PuppetParser, - ['pp']) - ::YARD::Handlers::Processor.register_handler_namespace(:puppet, - PuppetX::Puppet::Strings::YARD::Handlers) - - # FIXME: Might not be the best idea to have the template code on the Ruby - # LOAD_PATH as the contents of this directory really aren't library code. - ::YARD::Templates::Engine.register_template_path( - File.join(File.dirname(__FILE__), 'strings', 'yard', 'templates')) - end - end -end diff --git a/lib/puppet_x/puppet/strings/actions.rb b/lib/puppet_x/puppet/strings/actions.rb deleted file mode 100644 index dbbd87f..0000000 --- a/lib/puppet_x/puppet/strings/actions.rb +++ /dev/null @@ -1,92 +0,0 @@ -require 'puppet_x/puppet/strings' - -class PuppetX::Puppet::Strings::Actions - - # Creates a new instance of the Actions class by determining - # whether or not debug and backtrace arguments should be sent - # to YARD - def initialize(puppet_debug, puppet_backtrace) - @debug = puppet_debug - @backtrace = puppet_backtrace - end - - # Holds the name of a module and the file path to its YARD index - ModuleIndex = Struct.new(:name, :index_path) - - - # Maps things like the Puppet `--debug` flag to YARD options. - def merge_puppet_args!(yard_args) - yard_args.unshift '--debug' if @debug - yard_args.unshift '--backtrace' if @backtrace - - yard_args - end - - # Builds doc indices (.yardoc directories) for modules. - # Currently lacks the fine-grained control over where these - # indices are created and just dumps them in the module roots. - # - # @return [Array] the modules to be documented - # - # @param [Array] module_names a list of the module source files - # @param [Array] module_sourcefiles default list of module files - def index_documentation_for_modules(module_names, module_sourcefiles) - # NOTE: The return value of the `module` Face seems to have changed in - # 3.6.x. This part of the code will blow up if run under an earlier - # version of Puppet. - modules = Puppet::Face[:module, :current].list - module_list = modules[:modules_by_path].values.flatten - - module_list.select! {|m| module_names.include? m.name} unless module_names.empty? - - # Invoke `yardoc` with -n so that it doesn't generate any HTML output but - # does build a `.yardoc` index that other tools can generate output from. - yard_args = %w[--no-stats -n] + module_sourcefiles - merge_puppet_args!(yard_args) - - module_list.each do |m| - Dir.chdir(m.path) do - YARD::CLI::Yardoc.run(*yard_args) - - # Clear the global Registry so that objects from one module don't - # bleed into the next. - YARD::Registry.clear - end - end - end - - # Extracts the needed information of the modules we're documenting - # - # @return [Array] An array of representation of the modules - # to produce documentation for. Each ModuleIndex contains the module name - # and the path to its YARD index - # - # @param [Array] module_list a list of the module source files - def generate_module_tuples(module_list) - module_list.map do |mod| - name = (mod.forge_name || mod.name).gsub('/', '-') - yard_index = File.join(mod.path, '.yardoc') - - ModuleIndex.new(name, yard_index) - end - end - - # Hands off the needed information to YARD so it may - # serve the documentation - # - # @param [Array] yard_args a list of all the arguments to pass to YARD - def serve_documentation(*yard_args) - merge_puppet_args!(yard_args) - YARD::CLI::Server.run(*yard_args) - end - - # Hands off the needed information to YARD so it may - # generate the documentation - # - # @param [Array] yard_args a list of all the arguments to pass to YARD - def generate_documentation(*yard_args) - merge_puppet_args!(yard_args) - YARD::CLI::Yardoc.run(*yard_args) - end -end - diff --git a/lib/puppet_x/puppet/strings/pops/yard_statement.rb b/lib/puppet_x/puppet/strings/pops/yard_statement.rb deleted file mode 100644 index f618bf3..0000000 --- a/lib/puppet_x/puppet/strings/pops/yard_statement.rb +++ /dev/null @@ -1,79 +0,0 @@ -require 'ostruct' - -# An adapter class that conforms a Pops model instance + adapters to the -# interface expected by YARD handlers. -# -# FIXME: Inhertiting from OpenStruct is a bit of a hack. It allows attributes -# to be declared as needed but in the long run understandibility of the code -# would be improved by having a concrete model. -class PuppetX::Puppet::Strings::Pops::YARDStatement < OpenStruct - attr_reader :pops_obj, :comments - - def initialize(pops_obj) - # Initialize OpenStruct - super({}) - - unless pops_obj.is_a? Puppet::Pops::Model::PopsObject - raise ArgumentError, "A YARDStatement can only be initialized from a PopsObject. Got a: #{pops_obj.class}" - end - - @pops_obj = pops_obj - @pos_adapter = Puppet::Pops::Adapters::SourcePosAdapter.adapt(@pops_obj) - # FIXME: Perhaps this should be a seperate adapter? - @comments = extract_comments - end - - def type - pops_obj.class - end - - def line - @line ||= @pos_adapter.line - end - - def source - @source ||= @pos_adapter.extract_text - end - - # FIXME: I don't know quite what these are supposed to do, but they show up - # quite often in the YARD handler code. Figure out whether they are - # necessary. - alias_method :show, :source - def comments_hash_flag; nil end - def comments_range; nil end - - private - # TODO: This stuff should probably be part of a separate class/adapter. - COMMENT_PATTERN = /^\s*#.*\n/ - - def extract_comments - comments = [] - program = pops_obj.eAllContainers.find {|c| c.is_a?(Puppet::Pops::Model::Program) } - # FIXME: Horribly inefficient. Multiple copies. Generator pattern would - # be much better. - source_text = program.source_text.lines.to_a - - source_text.slice(0, line-1).reverse.each do |line| - if COMMENT_PATTERN.match(line) - # FIXME: The gsub trims comments, but is extremely optimistic: It - # assumes only one space separates the comment body from the - # comment character. - # NOTE: We cannot just trim any amount of whitespace as indentation - # is sometimes significant in markdown. We would need a real parser. - - # Comments which begin with some whitespace, a hash and then some - # tabs and spaces should be scrubbed. Comments which just have a - # solitary hash then a newline should keep that newline since newlines - # are significant in markdown. - comments.unshift line.gsub(/^\s*#[\t ]/, '').gsub(/^\s*#\n/, "\n") - else - # No comment found on this line. We must be done piecing together a - # comment block. - break - end - end - - # Stick everything back together. - comments.join - end -end diff --git a/lib/puppet_x/puppet/strings/pops/yard_transformer.rb b/lib/puppet_x/puppet/strings/pops/yard_transformer.rb deleted file mode 100644 index 01cbd0d..0000000 --- a/lib/puppet_x/puppet/strings/pops/yard_transformer.rb +++ /dev/null @@ -1,47 +0,0 @@ -# Loosely based on the TreeDumper classes in Pops::Model. The responsibility of -# this class is to walk a Pops::Model and output objects that can be consumed -# by YARD handlers. -# -# @note Currently, this class only extracts node, host class and type -# definitions. -class PuppetX::Puppet::Strings::Pops::YARDTransformer - def initialize - @transform_visitor = Puppet::Pops::Visitor.new(self, 'transform') - end - - def transform(o) - @transform_visitor.visit(o) - end - - private - - def transform_Factory(o) - transform(o.current) - end - - def transform_Program(o) - o.definitions.map{|d| transform(d)} - end - - # Extract comments from type definitions and class definitions. Wrap them - # into YARDStatement objects that provide an interface for YARD handlers. - def transform_NamedDefinition(o) - obj = PuppetX::Puppet::Strings::Pops::YARDStatement.new(o) - obj.parameters = o.parameters.map do |p| - param_tuple = [transform(p)] - param_tuple << ( p.value.nil? ? nil : transform(p.value) ) - end - - obj - end - - # Catch-all visitor. - def transform_Positioned(o) - PuppetX::Puppet::Strings::Pops::YARDStatement.new(o) - end - - # nil in... nil out! - def transform_NilClass(o) - nil - end -end diff --git a/lib/puppet_x/puppet/strings/util.rb b/lib/puppet_x/puppet/strings/util.rb deleted file mode 100644 index b99749c..0000000 --- a/lib/puppet_x/puppet/strings/util.rb +++ /dev/null @@ -1,65 +0,0 @@ -require 'puppet_x/puppet/strings/actions' - -module PuppetX::Puppet::Strings::Util - MODULE_SOURCEFILES = ['manifests/**/*.pp', 'lib/**/*.rb'] - - def self.generate(args = []) - yardoc_actions = PuppetX::Puppet::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) - - # The last element of the argument array should be the options hash. - # We don't have any options yet, so for now just pop the hash off and - # toss it. - # - # NOTE: The Puppet Face will throw 'unrecognized option' errors if any - # YARD options are passed to it. The best way to approach this problem is - # by using the `.yardopts` file. YARD will autoload any options placed in - # that file. - options = args.pop - YARD::Config.options = YARD::Config.options.merge(options) if options - - # For now, assume the remaining positional args are a list of manifest - # and ruby files to parse. - yard_args = (args.empty? ? MODULE_SOURCEFILES : args) - - # If json is going to be emitted to stdout, suppress statistics. - if options && options[:emit_json_stdout] - yard_args.push('--no-stats') - end - - # This line monkeypatches yard's progress indicator so it doesn't write - # all over the terminal. This should definitely not be in real code, but - # it's very handy for debugging with pry - #class YARD::Logger; def progress(*args); end; end - YARD::Tags::Library.define_directive("puppet.type.param", - :with_types_and_name, - PuppetX::Puppet::Strings::YARD::Tags::PuppetTypeParameterDirective) - - yardoc_actions.generate_documentation(*yard_args) - end - - def self.serve(args = []) - server_actions = PuppetX::Puppet::Strings::Actions.new(Puppet[:debug], Puppet[:trace]) - - args.pop - - module_names = args - - # FIXME: This is pretty inefficient as it forcibly re-generates the YARD - # indicies each time the server is started. However, it ensures things are - # generated properly. - module_list = server_actions.index_documentation_for_modules(module_names, MODULE_SOURCEFILES) - - module_tuples = server_actions.generate_module_tuples(module_list) - - module_tuples.map! do |mod| - [mod[:name], mod[:index_path]] - end - - # The `-m` flag means a list of name/path pairs will follow. The name is - # used as the module name and the path indicates which `.yardoc` index to - # generate documentation from. - yard_args = %w[-m -q] + module_tuples.flatten - - server_actions.serve_documentation(*yard_args) - end -end diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb deleted file mode 100644 index 5014908..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/defined_type_object.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'json' - -class PuppetX::Puppet::Strings::YARD::CodeObjects::DefinedTypeObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject - # A list of parameters attached to this class. - # @return [Array] - attr_accessor :parameters - attr_accessor :type_info - - def to_s - name.to_s - end - - def to_json(*a) - { - "name" => @name, - "file" => file, - "line" => line, - "parameters" => Hash[@parameters], - "docstring" => Puppet::Util::Docs.scrub(@docstring), - "signatures" => @type_info.map do |signature| - signature.map do |key, value| - { - "name" => key, - "type" => value, - } - end - end, - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - }.to_json(*a) - end -end diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb deleted file mode 100644 index 4234c15..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/host_class_object.rb +++ /dev/null @@ -1,22 +0,0 @@ -class PuppetX::Puppet::Strings::YARD::CodeObjects::HostClassObject < PuppetX::Puppet::Strings::YARD::CodeObjects::DefinedTypeObject - # The {HostClassObject} that this class inherits from, if any. - # @return [HostClassObject, Proxy, nil] - attr_accessor :parent_class - - # NOTE: `include_mods` is never used as it makes no sense for Puppet, but - # this is called by `YARD::Registry` and it will pass a parameter. - def inheritance_tree(include_mods = false) - if parent_class.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::HostClassObject) - # Cool. We got a host class. Return self + parent inheritance tree. - [self] + parent_class.inheritance_tree - elsif parent_class.is_a?(YARD::CodeObjects::Proxy) - # We have a reference to a parent that has not been created yet. Just - # return it. - [self, parent_class] - else - # Most likely no parent class. But also possibly an object that we - # shouldn't inherit from. Just return self. - [self] - end - end -end diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb deleted file mode 100644 index 5ce5bf8..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/method_object.rb +++ /dev/null @@ -1,62 +0,0 @@ -class YARD::CodeObjects::MethodObject - - # Override to_s and to_json methods in Yard's MethodObject so that they - # return output formatted as I like for puppet 3x and 4x methods. - def to_s - if self[:puppet_4x_function] || self[:puppet_3x_function] - name.to_s - else - super - end - end - - def to_json(*a) - if self[:puppet_4x_function] - { - "name" => @name, - "file" => file, - "line" => line, - "function_api_version" => 4, - "docstring" => Puppet::Util::Docs.scrub(@docstring), - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - "documented_params" => @parameters.map do |tuple| - { - "name" => tuple[0], - "type" => tuple[1], - } - end, - "signatures" => @type_info.map do |signature| - signature.map do |key, value| - { - "name" => key, - "type" => value, - } - end - end, - }.to_json(*a) - elsif self[:puppet_3x_function] - { - "name" => @name, - "file" => file, - "line" => line, - "function_api_version" => 3, - "docstring" => Puppet::Util::Docs.scrub(@docstring), - "documented_params" => @parameters.map do |tuple| - { - "name" => tuple[0], - "type" => tuple[1], - } - end, - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - }.to_json(*a) - else - super - end - end - - -end diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb deleted file mode 100644 index d56e598..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/provider_object.rb +++ /dev/null @@ -1,24 +0,0 @@ -class PuppetX::Puppet::Strings::YARD::CodeObjects::ProviderObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject - # A list of parameters attached to this class. - # @return [Array] - attr_accessor :parameters - - def to_json(*a) - { - "name" => @name, - "type_name" => @type_name, - "file" => file, - "line" => line, - "docstring" => Puppet::Util::Docs.scrub(@docstring), - "commands" => @commands, - "confines" => @confines, - "defaults" => @defaults, - "features" => @features, - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - }.to_json(*a) - end - - -end diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb deleted file mode 100644 index 6f6b3f1..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object.rb +++ /dev/null @@ -1,48 +0,0 @@ -class PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject < YARD::CodeObjects::NamespaceObject - - attr_accessor :type_info - # NOTE: `YARD::Registry#resolve` requires a method with this signature to - # be present on all subclasses of `NamespaceObject`. - def inheritance_tree(include_mods = false) - [self] - end - - def to_s - name.to_s - end - - def to_json(*a) - { - "name" => @name, - "file" => file, - "line" => line, - "docstring" => @docstring, - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - }.to_json(*a) - end - - # FIXME: We used to override `self.new` to ensure no YARD proxies were - # created for namespaces segments that did not map to a host class or - # defined type. Fighting the system in this way turned out to be - # counter-productive. - # - # However, if a proxy is left in, YARD will drop back to namspace-mangling - # heuristics that are very specific to Ruby and which produce ugly paths in - # the resulting output. Need to find a way to address this. - # - # Tried: - # - # - Overriding self.new in the code object. Failed because self.new - # overrides are gross and difficult to pull off. Especially when - # replacing an existing override. - # - # - Adding functionality to the base handler to ensure something other - # than a proxy occupies each namespace segment. Failed because once a - # code object is created with a namespace, it will never update. - # Unless that namespace is set to a Proxy. - # - # def self.new(namespace, name, *args, &block) -end - diff --git a/lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb b/lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb deleted file mode 100644 index b96b4a1..0000000 --- a/lib/puppet_x/puppet/strings/yard/code_objects/type_object.rb +++ /dev/null @@ -1,42 +0,0 @@ -class PuppetX::Puppet::Strings::YARD::CodeObjects::TypeObject < PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject - # A list of parameters attached to this class. - # @return [Array] - attr_accessor :parameters - - def to_json(*a) - { - "name" => @name, - "file" => file, - "line" => line, - "docstring" => Puppet::Util::Docs.scrub(@docstring), - "parameters" => @parameter_details.map do |obj| - { - "allowed_values" => obj[:allowed_values] ? obj[:allowed_values].flatten : [], - "default" => obj[:default], - "docstring" => Puppet::Util::Docs.scrub(obj[:desc] || ''), - "namevar" => obj[:namevar], - "name" => obj[:name], - } - end, - "examples" => self.tags.map do |tag| - tag.text if tag.tag_name == 'example' - end.compact, - "properties" => @property_details.map do |obj| - { - "allowed_values" => obj[:allowed_values] ? obj[:allowed_values].flatten : [], - "default" => obj[:default], - "docstring" => Puppet::Util::Docs.scrub(obj[:desc] || ''), - "name" => obj[:name], - } - end, - "features" => @features.map do |obj| - { - "docstring" => Puppet::Util::Docs.scrub(obj[:desc] || ''), - "methods" => obj[:methods], - "name" => obj[:name], - } - end, - }.to_json(*a) - end - -end diff --git a/lib/puppet_x/puppet/strings/yard/core_ext/yard.rb b/lib/puppet_x/puppet/strings/yard/core_ext/yard.rb deleted file mode 100644 index fa8a0d4..0000000 --- a/lib/puppet_x/puppet/strings/yard/core_ext/yard.rb +++ /dev/null @@ -1,39 +0,0 @@ -require 'yard' -require 'puppet_x/puppet/strings' - -# Patch the regular expression used to match namespaces -# so it will allow namespace segments that begin with -# both uppercase and lowercase letters (i.e. both -# Puppet::Namespace and puppet::namespace) -YARD::CodeObjects.send(:remove_const, :CONSTANTMATCH) -YARD::CodeObjects::CONSTANTMATCH = /[a-zA-Z]\w*/ - -# This is a temporary hack until a new version of YARD is -# released. We submitted a patch to YARD to add the -# CONSTANTSTART constant so that we could patch it and -# successfully match our own namesapces. However until -# the next version of the YARD gem is released, we must -# patch the problematic method itself as it is not yet -# using the added variable -if defined? YARD::CodeObjects::CONSTANTSTART - YARD::CodeObjects.send(:remove_const, :CONSTANTSTART) - YARD::CodeObjects::CONSTANTSTART = /^[a-zA-Z]/ -else - class YARD::CodeObjects::Proxy - def proxy_path - if @namespace.root? - (@imethod ? YARD::CodeObjects::ISEP : "") + name.to_s - elsif @origname - if @origname =~ /^[a-zA-Z]/ - @origname - else - [namespace.path, @origname].join - end - elsif name.to_s =~ /^[a-zA-Z]/ # const - name.to_s - else # class meth? - [namespace.path, name.to_s].join(YARD::CodeObjects::CSEP) - end - end - end -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/base.rb b/lib/puppet_x/puppet/strings/yard/handlers/base.rb deleted file mode 100644 index 462f973..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/base.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'puppet_x/puppet/strings/yard/core_ext/yard' - -class PuppetX::Puppet::Strings::YARD::Handlers::Base < ::YARD::Handlers::Base - # Easy access to Pops model objects for handler matching. - include Puppet::Pops::Model - # Easy access to custom code objects from which documentation is generated. - include PuppetX::Puppet::Strings::YARD::CodeObjects - - def self.handles?(statement) - handlers.any? {|h| h == statement.type} - end - -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb deleted file mode 100644 index b54f5cb..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/defined_type_handler.rb +++ /dev/null @@ -1,31 +0,0 @@ -class PuppetX::Puppet::Strings::YARD::Handlers::DefinedTypeHandler < PuppetX::Puppet::Strings::YARD::Handlers:: Base - handles ResourceTypeDefinition - - process do - obj = DefinedTypeObject.new(:root, statement.pops_obj.name) do |o| - o.parameters = statement.parameters.map do |a| - param_tuple = [a[0].pops_obj.name] - param_tuple << ( a[1].nil? ? nil : a[1].source ) - end - end - tp = Puppet::Pops::Types::TypeParser.new - param_type_info = {} - statement.pops_obj.parameters.each do |pop_param| - # If the parameter's type expression is nil, default to Any - if pop_param.type_expr == nil - param_type_info[pop_param.name] = Puppet::Pops::Types::TypeFactory.any() - else - begin - param_type_info[pop_param.name] = tp.interpret_any(pop_param.type_expr) - rescue Puppet::ParseError => e - # If the type could not be interpreted insert a prominent warning - param_type_info[pop_param.name] = "Type Error: #{e.message}" - end - end - end - obj.type_info = [param_type_info] - - - register obj - end -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb b/lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb deleted file mode 100644 index 072b469..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/heredoc_helper.rb +++ /dev/null @@ -1,82 +0,0 @@ -class HereDocHelper - # NOTE: The following methods duplicate functionality from - # Puppet::Util::Reference and Puppet::Parser::Functions.functiondocs - # - # However, implementing this natively in YARD is a good test for the - # feasibility of extracting custom Ruby documentation. In the end, the - # existing approach taken by Puppet::Util::Reference may be the best due to - # the heavy use of metaprogramming in Types and Providers. - - # Extracts the Puppet function name and options hash from the parsed - # definition. - # - # @return [(String, Hash{String => String})] - def process_parameters(statement) - # Passing `false` to prameters excludes the block param from the returned - # list. - name, opts = statement.parameters(false).compact - - name = process_element(name) - - # Don't try to process options if we don't have any - if !opts.nil? - opts = opts.map do |tuple| - # Jump down into the S-Expression that represents a hashrocket, `=>`, - # and the values on either side of it. - tuple.jump(:assoc).map{|e| process_element(e)} - end - - options = Hash[opts] - else - options = {} - end - - [name, options] - end - - # Sometimes the YARD parser returns Heredoc strings that start with `<-` - # instead of `<<-`. - HEREDOC_START = /^ e - # If the type could not be interpreted insert a prominent warning - param_type_info[pop_param.name] = "Type Error: #{e.message}" - end - end - end - obj.type_info = [param_type_info] - - statement.pops_obj.tap do |o| - if o.parent_class - obj.parent_class = P(:root, o.parent_class) - end - end - - register obj - rescue StandardError, SystemStackError => e - # If we hit this, we've thrown an exception somewhere that should be - # addressed but should not break the build. - # - # SystemStackError is being caught due to a presently untraced bug in - # either YARD or the Puppet Parser. - # - # Note: Documentation will *not* be generated for any item listed here, - # but you will get the rest of your documentation! - - $stderr.puts("Ignored: #{e.inspect} at #{obj.title}") - end - end -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb deleted file mode 100644 index 8970086..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/provider_handler.rb +++ /dev/null @@ -1,96 +0,0 @@ -# Handles `dispatch` calls within a future parser function declaration. For -# now, it just treats any docstring as an `@overlaod` tag and attaches the -# overload to the parent function. -class PuppetX::Puppet::Strings::YARD::Handlers::PuppetProviderHandler < YARD::Handlers::Ruby::Base - include PuppetX::Puppet::Strings::YARD::CodeObjects - - handles :command_call, :call - - process do - @heredoc_helper = HereDocHelper.new - # Puppet types always begin with: - # Puppet::Types.newtype... - # Therefore, we match the corresponding trees which look like this: - # s(:call, - # s(:const_path_ref, - # s(:var_ref, s(:const, "Puppet", ...), ...), - # s(:const, "Type", ...), - # You think this is ugly? It's better than the alternative. - return unless statement.children.length > 2 - first = statement.children.first.first - return unless (first.source == 'Puppet::Type') || - (first.type == :var_ref && - first.source == 'Type') && - statement[2].source == 'provide' - i = statement.index { |s| YARD::Parser::Ruby::AstNode === s && s.type == :ident && s.source == 'provide' } - provider_name = statement[i+1].jump(:ident).source - type_name = statement.jump(:symbol).first.source - provider_name = "#{type_name}:#{provider_name}" - - obj = ProviderObject.new(:root, "#{provider_name}_provider") - - docstring = nil - features = [] - commands = [] - confines = {} - defaults = {} - do_block = statement.jump(:do_block) - do_block.traverse do |node| - if is_a_func_call_named?('desc', node) - content = node.jump(:tstring_content) - # if we found the string content extract its source - if content != node - # The docstring is either the source stripped of heredoc - # annotations or the raw source. - if @heredoc_helper.is_heredoc?(content.source) - docstring = @heredoc_helper.process_heredoc content.source - else - docstring = content.source - end - end - elsif is_a_func_call_named?('confine', node) - node.traverse do |s| - if s.type == :assoc - k = s.first.jump(:ident).source - v = s[1].first.source - confines[k] = v - end - end - elsif is_a_func_call_named?('has_feature', node) - list = node.jump :list - if list != nil && list != node - features += list.map { |s| s.source if YARD::Parser::Ruby::AstNode === s }.compact - end - elsif is_a_func_call_named?('commands', node) - assoc = node.jump(:assoc) - if assoc && assoc != node - ident = assoc.jump(:ident) - if ident && ident != assoc - commands << ident.source - end - end - elsif is_a_func_call_named?('defaultfor', node) - node.traverse do |s| - if s.type == :assoc - k = s.first.jump(:ident).source - v = s[1].first.source - defaults[k] = v - end - end - end - end - obj.features = features - obj.commands = commands - obj.confines = confines - obj.defaults = defaults - obj.type_name = type_name - obj.header_name = provider_name - - register_docstring(obj, docstring, nil) - register obj - end - - def is_a_func_call_named?(name, node) - (node.type == :fcall || node.type == :command || node.type == :vcall) && node.children.first.source == name - end -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb deleted file mode 100644 index 183c120..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler.rb +++ /dev/null @@ -1,54 +0,0 @@ -require File.join(File.dirname(__FILE__),'./heredoc_helper') - -class PuppetX::Puppet::Strings::YARD::Handlers::Puppet3xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::Puppet::Strings::YARD::CodeObjects - - handles method_call(:newfunction) - - process do - @heredoc_helper = HereDocHelper.new - name, options = @heredoc_helper.process_parameters statement - - obj = MethodObject.new(function_namespace, name) - obj[:puppet_3x_function] = true - - register obj - if options['doc'] - register_docstring(obj, options['doc'], nil) - end - - # This has to be done _after_ register_docstring as all tags on the - # object are overwritten by tags parsed out of the docstring. - return_type = options['type'] - return_type ||= 'statement' # Default for newfunction - obj.add_tag YARD::Tags::Tag.new(:return, '', return_type) - - # FIXME: This is a hack that allows us to document the Puppet Core which - # uses `--no-transitive-tag api` and then only shows things explicitly - # tagged with `public` or `private` api. This is kind of insane and - # should be fixed upstream. - obj.add_tag YARD::Tags::Tag.new(:api, 'public') - end - - private - - # Returns a {PuppetNamespaceObject} for holding functions. Creates this - # object if necessary. - # - # @return [PuppetNamespaceObject] - def function_namespace - # NOTE: This tricky. If there is ever a Ruby class or module with the - # name ::Puppet3xFunctions, then there will be a clash. Hopefully the name - # is sufficiently uncommon. - obj = P(:root, 'Puppet3xFunctions') - if obj.is_a? Proxy - namespace_obj = PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') - namespace_obj.add_tag YARD::Tags::Tag.new(:api, 'public') - - register namespace_obj - end - - obj - end - -end diff --git a/lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb b/lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb deleted file mode 100644 index b301b6e..0000000 --- a/lib/puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler.rb +++ /dev/null @@ -1,234 +0,0 @@ -# Handles `dispatch` calls within a future parser function declaration. For -# now, it just treats any docstring as an `@overlaod` tag and attaches the -# overload to the parent function. -class PuppetX::Puppet::Strings::YARD::Handlers::Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::Puppet::Strings::YARD::CodeObjects - - handles method_call(:dispatch) - - process do - return unless owner.is_a?(MethodObject) && owner['puppet_4x_function'] - return unless statement.docstring - - docstring = ::YARD::Docstring.new(statement.docstring, nil) - - # FIXME: This does a wholesale copy of all possible tags. But, we're only - # interested in the @overload tag. - owner.add_tag *docstring.tags - end -end - -class Puppet4xFunctionHandler < YARD::Handlers::Ruby::Base - include PuppetX::Puppet::Strings::YARD::CodeObjects - - handles method_call(:create_function) - - # Given a command node which represents code like this: - # param 'Optional[Type]', :value_type - # Extract the type name and type signature and return them as a array. - def extract_type_from_command command - return [] if command.children.length < 2 or command.children[1].children.length < 2 - type_specifier = command.children[1] - # the parameter signature is the first child of the specifier and an - # identifier. Jump to the content inside the quotes and convert it to a - # string. - param_signature = type_specifier.children[0].jump(:tstring_content).source - # The parameter name is the second child of the specifier and a symbol. - # convert it to a string. - param_name_ident = type_specifier.jump :ident - return [] if param_name_ident == type_specifier - param_name = param_name_ident.source - [param_name, param_signature] - end - - process do - name = process_parameters - - method_arguments = [] - - # To attach the method parameters to the new code object, traverse the - # ruby AST until a node is found which defines a array of parameters. - # Then, traverse the children of the parameters, storing each identifier - # in the array of method arguments. - obj = MethodObject.new(function_namespace, name) do |o| - end - - # The data structure for overload_signatures is an array of hashes. Each - # hash represents the arguments a single function dispatch (aka overload) - # can take. - # overload_signatures = [ - # { # First function dispatch arguments - # # argument name, argument type - # 'arg0': 'Variant[String,Array[String]]', - # 'arg1': 'Optional[Type]' - # }, - # { # Second function dispatch arguments - # 'arg0': 'Variant[String,Array[String]]', - # 'arg1': 'Optional[Type]', - # 'arg2': 'Any' - # } - # ] - # Note that the order for arguments to a function doesn't actually matter - # because we allow users flexibility when listing their arguments in the - # comments. - overload_signatures = [] - statement.traverse do |node| - # Find all of the dispatch methods - if node.type == :ident and node.source == 'dispatch' - command = node.parent - do_block = command.jump :do_block - # If the command doesn't have a do_block we can't extract type info - if do_block == command - next - end - signature = {} - # Iterate through each of the children of the do block and build - # tuples of parameter names and parameter type signatures - do_block.children.first.children.each do |child| - name, type = extract_type_from_command(child) - # This can happen if there is a function or something we aren't - # expecting. - if name != nil and type != nil - signature[name] = type - end - end - overload_signatures <<= signature - end - end - - # If the overload_signatures list is empty because we couldn't find any - # dispatch blocks, then there must be one function named the same as the - # name of the function being created. - if overload_signatures.length == 0 - statement.traverse do |node| - # Find the function definition with the same name as the puppet - # function being created. - if (node.type == :def and node.children.first.type == :ident and - node.children.first.source == obj.name.to_s) - signature = {} - # Find its parameters. If they don't exist, fine - params = node.jump :params - break if params == node - params.traverse do |param| - if param.type == :ident - # The parameters of Puppet functions with no defined dispatch are - # as though they are Any type. - signature[param[0]] = 'Any' - end - end - overload_signatures <<= signature - # Now that the parameters have been found, break out of the traversal - break - end - end - end - - # Preserve this type information. We'll need it later when we look - # at the docstring. - obj.type_info = overload_signatures - - # The yard docstring parser expects a list of lists, not a list of lists of - # lists. - obj.parameters = overload_signatures.map { |sig| sig.to_a }.flatten(1) - - obj['puppet_4x_function'] = true - - register obj - - obj.add_tag YARD::Tags::Tag.new(:api, 'public') - - blk = statement.block.children.first - parse_block(blk, :owner => obj) - end - - private - - # Returns a {PuppetNamespaceObject} for holding functions. Creates this - # object if necessary. - # - # @return [PuppetNamespaceObject] - def function_namespace - # NOTE: This tricky. If there is ever a Ruby class or module with the - # name ::Puppet4xFunctions, then there will be a clash. Hopefully the name - # is sufficiently uncommon. - obj = P(:root, 'Puppet4xFunctions') - if obj.is_a? Proxy - namespace_obj = PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') - - register namespace_obj - # FIXME: The docstring has to be cleared. Otherwise, the namespace - # object will be registered using the docstring of the - # `create_function` call that is currently being processed. - # - # Figure out how to properly register the namespace without using the - # function handler object. - register_docstring(namespace_obj, '', nil) - namespace_obj.add_tag YARD::Tags::Tag.new(:api, 'public') - end - - obj - end - - # NOTE: The following methods duplicate functionality from - # Puppet::Util::Reference and Puppet::Parser::Functions.functiondocs - # - # However, implementing this natively in YARD is a good test for the - # feasibility of extracting custom Ruby documentation. In the end, the - # existing approach taken by Puppet::Util::Reference may be the best due to - # the heavy use of metaprogramming in Types and Providers. - - # Extracts the Puppet function name and options hash from the parsed - # definition. - # - # @return [(String, Hash{String => String})] - def process_parameters - # Passing `false` to parameters excludes the block param from the returned - # array. - name, _ = statement.parameters(false).compact - - name = process_element(name) - - - name - end - - # Sometimes the YARD parser returns Heredoc strings that start with `<-` - # instead of `<<-`. - HEREDOC_START = /^ 2 - first = statement.children.first - return unless (first.type == :const_path_ref and - first.source == 'Puppet::Type') or - (first.type == :var_ref and - first.source == 'Type') and - statement.children[1].source == "newtype" - - # Fetch the docstring for the types. The docstring is the string literal - # assigned to the @doc parameter or absent, like this: - # @doc "docstring goes here" - # We assume that docstrings nodes have the following shape in the source - # code: - # ... - # s(s(:assign, - # s(:..., s(:ivar, "@doc", ...), ...), - # s(:..., - # s(:..., - # s(:tstring_content, - # "Manages files, including their content, etc.", ... - # Initialize the docstring to nil, the default value if we don't find - # anything - docstring = nil - # Walk the tree searching for assignments - statement.traverse do |node| - if node.type == :assign - # Once we have found and assignment, jump to the first ivar - # (the l-value) - # If we can't find an ivar return the node. - ivar = node.jump(:ivar) - # If we found and ivar and its source reads '@doc' then... - if ivar != node and ivar.source == '@doc' - # find the next string content - content = node.jump(:tstring_content) - # if we found the string content extract its source - if content != node - # The docstring is either the source stripped of heredoc - # annotations or the raw source. - if @heredoc_helper.is_heredoc? content.source - docstring = @heredoc_helper.process_heredoc content.source - else - docstring = content.source - end - end - # Since we found the @doc parameter (regardless of whether we - # successfully extracted its source), we're done. - break - # But if we didn't find the ivar loop around again. - else - next - end - end - end - - # The types begin with: - # Puppet::Types.newtype(:symbol) - # Jump to the first identifier (':symbol') after the third argument - # ('(:symbol)') to the current statement - name = statement.children[2].jump(:ident).source - parameter_details = [] - property_details = [] - features = [] - obj = TypeObject.new(:root, name) - obj.parameters = [] - - # Find the do block following the Type. - do_block = statement.jump(:do_block) - # traverse the do block's children searching for function calls whose - # identifier is newparam (we're calling the newparam function) - do_block.traverse do |node| - if is_param? node - # The first member of the parameter tuple is the parameter name. - # Find the second identifier node under the fcall tree. The first one - # is 'newparam', the second one is the function name. - # Get its source. - # The second parameter is nil because we cannot infer types for these - # functions. In fact, that's a silly thing to ask because ruby - # types were deprecated with puppet 4 at the same time the type - # system was created. - - # Because of a ripper bug a symbol identifier is sometimes incorrectly parsed as a keyword. - # That is, the symbol `:true` will be represented as s(:symbol s(:kw, true... - param_name = node.children[1].jump(:ident) - if param_name == node.children[1] - param_name = node.children[1].jump(:kw) - end - param_name = param_name.source - obj.parameters << [param_name, nil] - parameter_details << {:name => param_name, - :desc => fetch_description(node), :exists? => true, - :puppet_type => true, - :default => fetch_default(node), - :namevar => is_namevar?(node, param_name, name), - :parameter => true, - :allowed_values => get_parameter_allowed_values(node), - } - elsif is_prop? node - # Because of a ripper bug a symbol identifier is sometimes incorrectly parsed as a keyword. - # That is, the symbol `:true` will be represented as s(:symbol s(:kw, true... - prop_name = node.children[1].jump(:ident) - if prop_name == node.children[1] - prop_name = node.children[1].jump(:kw) - end - prop_name = prop_name.source - property_details << {:name => prop_name, - :desc => fetch_description(node), :exists? => true, - :default => fetch_default(node), - :puppet_type => true, - :property => true, - :allowed_values => get_property_allowed_values(node), - } - elsif is_feature? node - features << get_feature(node) - elsif is_a_func_call_named? 'ensurable', node - # Someone could call the ensurable method and create an ensure - # property. If that happens, they it will be documented twice. Serves - # them right. - property_details << {:name => 'ensure', - :desc => '', :exists? => true, - :default => nil, - :puppet_type => true, - :property => true, - :allowed_values => [], - } - end - end - obj.parameter_details = parameter_details - obj.property_details = property_details - obj.features = features - obj.header_name = name - - register obj - # Register docstring after the object. If the object already has a - # docstring, or more likely has parameters documented with the type - # directive and an empty docstring, we want to override it with the - # docstring we found, assuming we found one. - register_docstring(obj, docstring, nil) if docstring - end - - - # See: - # https://docs.puppet.com/guides/custom_types.html#namevar - # node should be a parameter - def is_namevar? node, param_name, type_name - # Option 1: - # Puppet::Type.newtype(:name) do - # ... - # newparam(:name) do - # ... - # end - if type_name == param_name - return true - end - # Option 2: - # newparam(:path, :namevar => true) do - # ... - # end - if node.children.length >= 2 - node.traverse do |s| - if s.type == :assoc and s.jump(:ident).source == 'namevar' and s.jump(:kw).source == 'true' - return true - end - end - end - # Option 3: - # newparam(:path) do - # isnamevar - # ... - # end - do_block = node.jump(:do_block).traverse do |s| - if is_a_func_call_named? 'isnamevar', s - return true - end - end - # Crazy implementations of types may just call #isnamevar directly on the object. - # We don't handle this today. - return false - end - - def is_param? node - is_a_func_call_named? 'newparam', node - end - def is_prop? node - is_a_func_call_named? 'newproperty', node - end - - def is_feature? node - is_a_func_call_named? 'feature', node - end - - def is_a_func_call_named? name, node - (node.type == :fcall or node.type == :command or node.type == :vcall) and node.children.first.source == name - end - - def get_feature node - name = node[1].jump(:ident).source - desc = node[1].jump(:tstring_content).source - methods = [] - if node[1].length == 4 and node.children[1][2].jump(:ident).source == 'methods' - arr = node[1][2].jump(:array) - if arr != node[1][2] - arr.traverse do |s| - if s.type == :ident - methods << s.source - end - end - end - end - { - :name => name, - :desc => desc, - :methods => methods != [] ? methods : nil, - } - end - - def get_parameter_allowed_values node - vals = [] - node.traverse do |s| - if is_a_func_call_named? 'newvalues', s - list = s.jump(:list) - if list != s - vals += list.map { |item| [item.source] if YARD::Parser::Ruby::AstNode === item } - end - end - end - vals.compact - end - - # Calls to newvalue only apply to properties, according to Dan & Nan's - # "Puppet Types and Providers", page 30. - def get_property_allowed_values node - vals = get_parameter_allowed_values node - node.traverse do |s| - if is_a_func_call_named? 'newvalue', s - required_features = nil - s.traverse do |ss| - if ss.type == :assoc and ss[0].source == ':required_features' - required_features = ss[1].source - end - end - list = s.jump(:list) - if list != s - vals << [list[0].source, required_features].compact - end - end - end - vals - end - - def fetch_default node - do_block = node.jump(:do_block) - do_block.traverse do |s| - if is_a_func_call_named? 'defaultto', s - return s[-1].source - end - end - nil - end - - def fetch_description(fcall) - fcall.traverse do |node| - if is_a_func_call_named? 'desc', node - content = node.jump(:string_content) - if content != node - @heredoc_helper = HereDocHelper.new - if @heredoc_helper.is_heredoc? content.source - docstring = @heredoc_helper.process_heredoc content.source - else - docstring = content.source - end - return docstring - end - end - end - return nil - end -end diff --git a/lib/puppet_x/puppet/strings/yard/json_registry_store.rb b/lib/puppet_x/puppet/strings/yard/json_registry_store.rb deleted file mode 100644 index 22729c4..0000000 --- a/lib/puppet_x/puppet/strings/yard/json_registry_store.rb +++ /dev/null @@ -1,85 +0,0 @@ -module YARD - - class JsonRegistryStore < RegistryStore - def save(merge=true, file=nil) - super - - @serializer = Serializers::JsonSerializer.new(@file) - - sdb = Registry.single_object_db - if sdb == true || sdb == nil - serialize_output_schema(@store) - else - values(false).each do |object| - serialize_output_schema(object) - end - end - true - end - - # @param obj [Hash] A hash representing the registry or part of the - # registry. - def serialize_output_schema(obj) - - schema = { - :puppet_functions => [], - :puppet_providers => [], - :puppet_classes => [], - :defined_types => [], - :puppet_types => [], - } - - schema[:puppet_functions] += obj.select do |key, val| - val.type == :method and (val['puppet_4x_function'] or - val['puppet_3x_function']) - end.values - - schema[:puppet_classes] += obj.select do |key, val| - val.type == :hostclass - end.values - - schema[:defined_types] += obj.select do |key, val| - val.type == :definedtype - end.values - - schema[:puppet_providers] += obj.select do |key, val| - val.type == :provider - end.values - - schema[:puppet_types] += obj.select do |key, val| - val.type == :type - end.values - - @serializer.serialize(schema.to_json) - end - end - - # Override the serializer because it puts the data at a wacky path and, more - # importantly, marshals the data with a bunch of non-printable characters. - module Serializers - class JsonSerializer < YardocSerializer - - def initialize o - super - @options = { - :basepath => '.', - :extension => 'json', - } - @extension = 'json' - @basepath = '.' - end - def serialize(data) - - if YARD::Config.options[:emit_json] - path = YARD::Config.options[:emit_json] - log.debug "Serializing json to #{path}" - File.open!(path, "wb") {|f| f.write data } - end - if YARD::Config.options[:emit_json_stdout] - puts data - end - end - end - end - -end diff --git a/lib/puppet_x/puppet/strings/yard/monkey_patches.rb b/lib/puppet_x/puppet/strings/yard/monkey_patches.rb deleted file mode 100644 index f509fb6..0000000 --- a/lib/puppet_x/puppet/strings/yard/monkey_patches.rb +++ /dev/null @@ -1,68 +0,0 @@ -require 'yard' -require File.join(File.dirname(__FILE__), './json_registry_store') - -# TODO: As far as I can tell, monkeypatching is the officially recommended way -# to extend these tools to cover custom usecases. Follow up on the YARD mailing -# list or IRC to see if there is a better way. - -class YARD::CLI::Yardoc - def all_objects - YARD::Registry.all(:root, :module, :class, :type, :provider, :puppetnamespace, :hostclass, :definedtype) - end -end - -class YARD::CLI::Stats - def stats_for_hostclasses - output 'Puppet Classes', *type_statistics(:hostclass) - end - - def stats_for_definedtypes - output 'Puppet Defined Types', *type_statistics(:definedtype) - end - - def stats_for_puppet_types - output 'Puppet Types', *type_statistics(:type) - end - - def stats_for_puppet_provider - output 'Puppet Providers', *type_statistics(:provider) - end -end - -class YARD::Logger - def show_progress - return false if YARD.ruby18? # threading is too ineffective for progress support - return false if YARD.windows? # windows has poor ANSI support - return false unless io.tty? # no TTY support on IO - # Here is the actual monkey patch. A simple fix to an inverted conditional. - # Without this Pry is unusable for debugging as the progress bar goes - # craaaaaaaazy. - return false unless level > INFO # no progress in verbose/debug modes - @show_progress - end - - # Redirect Yard command line warnings to a log file called .yardwarns - # Yard warnings may be irrelevant, spurious, or may not conform with our - # styling and UX design. They are also printed on stdout by default. - def warn warning - f = File.new '.yardwarns', 'a' - f.write warning - f.close() - end -end - - -# 15:04:42 radens | lsegal: where would you tell yard to use your custom RegistryStore? -# 15:09:54 @lsegal | https://github.com/lsegal/yard/blob/master/lib/yard/registry.rb#L428-L435 -# 15:09:54 @lsegal | you would set that attr on Registry -# 15:09:54 @lsegal | it might be worth expanding that API to swap out the store class used -# 15:10:49 @lsegal | specifically -# | https://github.com/lsegal/yard/blob/master/lib/yard/registry.rb#L190 and -# | replace RegistryStore there with a storage_class attr -module YARD::Registry - class << self - def clear - self.thread_local_store = YARD::JsonRegistryStore.new - end - end -end diff --git a/lib/puppet_x/puppet/strings/yard/parser.rb b/lib/puppet_x/puppet/strings/yard/parser.rb deleted file mode 100644 index b309a06..0000000 --- a/lib/puppet_x/puppet/strings/yard/parser.rb +++ /dev/null @@ -1,30 +0,0 @@ -require 'yard' -require 'puppet/pops' - -require 'puppet_x/puppet/strings' -require 'puppet_x/puppet/strings//pops/yard_transformer' - -class PuppetX::Puppet::Strings::YARD::PuppetParser < YARD::Parser::Base - attr_reader :file, :source - - def initialize(source, filename) - @source = source - @file = filename - - @parser = Puppet::Pops::Parser::Parser.new() - @transformer = PuppetX::Puppet::Strings::Pops::YARDTransformer.new() - end - - def parse - @parse_result ||= @parser.parse_string(source) - self - end - - def enumerator - statements = @transformer.transform(@parse_result) - - # Ensure an array is returned and prune any nil values. - Array(statements).compact.reverse - end - -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb deleted file mode 100644 index 900985f..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/docstring.erb +++ /dev/null @@ -1,34 +0,0 @@ -
-
-

<%= htmlify(@class_details[:desc]) %>

-
-
-
- <% if @class_details[:examples] != {}%> -
-

Examples:

- <% @class_details[:examples].each do |title, text| %> -

<%= title %>

-
<%= text %>
- <% end %> -
- <% end %> - <% if @class_details[:since] %> -

Since:

-
    -
  • -
    -

    <%= @class_details[:since] %>

    -
    -
  • -
- <% end %> - <% if @class_details[:return] %> -

Return:

-
    -
  • - <%= @html_helper.generate_return_types(@class_details[:return][1], @class_details[:return][0]) %> -
  • -
- <% end %> -
diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb deleted file mode 100644 index 74b3dba..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/header.erb +++ /dev/null @@ -1,5 +0,0 @@ -
-

- <%= @header_text %> -

-
diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb deleted file mode 100644 index d03666e..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/parameter_details.erb +++ /dev/null @@ -1,6 +0,0 @@ -

Parameter Summary

-
-
    - <%= @html_helper.generate_parameters(@param_details, object) %> -
-
diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb deleted file mode 100644 index 91e114a..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/html/setup.rb +++ /dev/null @@ -1 +0,0 @@ -include T('default/module/html') diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb deleted file mode 100644 index 48f2877..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/definedtype/setup.rb +++ /dev/null @@ -1,49 +0,0 @@ -include T('default/module') - -require File.join(File.dirname(__FILE__),'../html_helper') -require File.join(File.dirname(__FILE__),'../template_helper') - -def init - sections :header, :box_info, :pre_docstring, :docstring, :parameter_details - - @template_helper = TemplateHelper.new - @html_helper = HTMLHelper.new - @template_helper.check_parameters_match_docs object - params = object.parameters.map { |param| param.first } - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} - param_details = @template_helper.extract_param_details(params, param_tags) unless params.nil? - @template_helper.check_types_match_docs object, param_details - -end - -def parameter_details - return if object.parameters.empty? - - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} - params = object.parameters - - @param_details = [] - - @param_details = @template_helper.extract_param_details(params, param_tags, true) - - erb(:parameter_details) -end - -def header - if object.type == :hostclass - @header_text = "Puppet Class: #{object.name}" - elsif object.type == :definedtype - @header_text = "Puppet Defined Type: #{object.name}" - else - @header_text = "#{object.name}" - end - - erb(:header) -end - -def docstring - - @class_details = @template_helper.extract_tag_data(object) - - erb(:docstring) -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb deleted file mode 100644 index 38081a0..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_class.erb +++ /dev/null @@ -1,2 +0,0 @@ -
  • <%= link_object(Registry.root, Registry.root.title, nil, false) %>
  • -<%= namespace_list %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb deleted file mode 100644 index 6ba286e..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_manifest.erb +++ /dev/null @@ -1 +0,0 @@ -<%= namespace_list(:namespace_types => [:hostclass, :definedtype]) %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb deleted file mode 100644 index 241b6cc..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_plugin.erb +++ /dev/null @@ -1,21 +0,0 @@ -<% unless P(:root, 'Puppet3xFunctions').is_a?(CodeObjects::Proxy) %> -
  • - - <%= link_object(P(:root, 'Puppet3xFunctions'), 'Puppet 3x Functions', nil, false) %> - Puppet3xFunctions -
  • -
      - <%= namespace_list(:root => P(:root,'Puppet3xFunctions'), :namespace_types => [:puppetnamespace, :method]) %> -
    -<% end %> - -<% unless P(:root, 'Puppet4xFunctions').is_a?(CodeObjects::Proxy) %> -
  • - - <%= link_object(P(:root, 'Puppet4xFunctions'), 'Puppet 4x Functions', nil, false) %> - Puppet4xFunctions -
  • -
      - <%= namespace_list(:root => P(:root,'Puppet4xFunctions'), :namespace_types => [:puppetnamespace, :method]) %> -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb deleted file mode 100644 index 582fe67..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb +++ /dev/null @@ -1 +0,0 @@ -<%= namespace_list(:namespace_types => [:provider]) %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb deleted file mode 100644 index 14748c8..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb +++ /dev/null @@ -1 +0,0 @@ -<%= namespace_list(:namespace_types => [:type]) %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb deleted file mode 100644 index ed09a8f..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/fulldoc/html/setup.rb +++ /dev/null @@ -1,82 +0,0 @@ -def generate_class_list - @items = options.objects.select{|o| [:module, :class, :root].include? o.type} if options.objects - @list_title = "Class List" - @list_type = "class" - generate_list_contents -end - -def generate_puppet_manifest_list - @items = options.objects.select{|o| [:hostclass, :definedtype].include? o.type} if options.objects - @list_title = "Puppet Manifest List" - # This is important. It causes some YARD JavaScript bits to hook in and - # perform the correct formatting. - @list_class = "class" - @list_type = "puppet_manifest" - generate_list_contents -end - -def generate_puppet_plugin_list - # NOTE: PuppetNamaspaceObject might eventually be used for more than just a - # container for plugins... - @items = options.objects.select{|o| [:puppetnamespace].include? o.type} if options.objects - @list_title = "Puppet Plugin List" - # This is important. It causes some YARD JavaScript bits to hook in and - # perform the correct formatting. - @list_class = "class" - @list_type = "puppet_plugin" - generate_list_contents -end - -def generate_puppet_type_list - @items = options.objects.select{|o| [:type].include? o.type} if options.objects - @list_title = "Puppet Type List" - @list_type = "puppet_type" - generate_list_contents -end - -def generate_puppet_provider_list - @items = options.objects.select{|o| [:provider].include? o.type} if options.objects - @list_title = "Puppet Provider List" - @list_type = "puppet_provider" - generate_list_contents -end - -# A hacked version of class_list that can be instructed to only display certain -# namespace types. This allows us to separate Puppet bits from Ruby bits. -def namespace_list(opts = {}) - o = { - :root => Registry.root, - :namespace_types => [:module, :class] - }.merge(opts) - - root = o[:root] - namespace_types = o[:namespace_types] - - out = "" - children = run_verifier(root.children) - if root == Registry.root - children += @items.select {|o| o.namespace.is_a?(CodeObjects::Proxy) } - end - children.reject {|c| c.nil? }.sort_by {|child| child.path }.map do |child| - if namespace_types.include? child.type - if child.namespace.is_a?(CodeObjects::Proxy) - name = child.path - elsif child.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::TypeObject) || child.is_a?(PuppetX::Puppet::Strings::YARD::CodeObjects::ProviderObject) - name = child.header_name - else - name = child.name - end - has_children = child.respond_to?(:children) && run_verifier(child.children).any? {|o| o.is_a?(CodeObjects::NamespaceObject) } - out << "
  • " - out << " " if has_children - out << linkify(child, name) - out << " < #{child.superclass.name}" if child.is_a?(CodeObjects::ClassObject) && child.superclass - out << "" - out << child.namespace.title - out << "" - out << "
  • " - out << "
      #{namespace_list(:root => child, :namespace_types => namespace_types)}
    " if has_children - end - end - out -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb deleted file mode 100644 index 334c764..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/box_info.erb +++ /dev/null @@ -1,22 +0,0 @@ -<% n = 1 %> -
    - <% if object.parent_class %> -
    Inherits:
    -
    - <%= linkify object.parent_class, object.parent_class.path %> -
      - <% object.inheritance_tree.reverse.each_with_index do |obj, i| %> - - <% end %> -
    - show all -
    - <% n = 2 %> - <% end %> - <% unless object.root? %> -
    Defined in:
    -
    <%= erb(:defines) %>
    - <% end %> -
    -
    - diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb deleted file mode 100644 index 3cb9cdf..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/setup.rb +++ /dev/null @@ -1 +0,0 @@ -include T('default/definedtype/html') diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb deleted file mode 100644 index 3948080..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/html/subclasses.erb +++ /dev/null @@ -1,4 +0,0 @@ -
    -

    Direct Known Subclasses

    -

    <%= @subclasses.map {|child| linkify(child, child.path) }.join(", ") %>

    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb deleted file mode 100644 index b8bda9e..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/hostclass/setup.rb +++ /dev/null @@ -1,21 +0,0 @@ -include T('default/definedtype') - -def init - super - sections.push :subclasses -end - -def subclasses - # The naming is a bit weird because Ruby classes use `globals.subclasses`. - unless globals.hostsubclasses - globals.hostsubclasses = {} - list = run_verifier Registry.all(:hostclass) - list.each {|o| (globals.hostsubclasses[o.parent_class.path] ||= []) << o if o.parent_class } - end - - @subclasses = globals.hostsubclasses[object.path] - - return if @subclasses.nil? || @subclasses.empty? - erb(:subclasses) -end - diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb b/lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb deleted file mode 100644 index 463371c..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/html_helper.rb +++ /dev/null @@ -1,139 +0,0 @@ -# A class containing helper methods to aid the generation of HTML -# given formatted data -class HTMLHelper - - # Generates the HTML to format the relevant data about return values - def generate_return_types(types, desc = nil) - result = [] - - result << "(" << types.join(", ") << ")" - - if !desc.nil? - result << "-

    #{desc}

    " - end - - result.join - end - - def generate_features features, object - result = [] - - if features - features.each do |feat| - result << "
  • " - result << "#{feat[:name]} " - if feat[:desc] - result << "-

    #{feat[:desc]}

    " - end - if feat[:methods] - result << "

    Methods

    " - result << "
      " - feat[:methods].each do |method| - result << "
    • " << method << "
    • " - end - result << "
    " - end - result << "
  • " - end - end - result.join - end - - # Generates the HTML to format the relevant data about parameters - def generate_parameters(params, object) - result = [] - - params.each do |param| - result << "
  • " - - # Parameters which are documented in the comments but not - # present in the code itself are given the strike through - # styling in order to show the reader that they do not actually - # exist - if !param[:exists?] - result << "" - end - - result << "#{param[:name]} " - result << "" - - # If the docstring specifies types, use those - if param[:types] - result << "(" << "" << param[:types].join(", ") << "" << ")" - # Otherwise, if typing information could be extracted from the object - # itself, use that - elsif object.type_info - # If the parameter name includes the default value, scrub that. - if param[:name].match(/([^=]*)=/) - param_name = $1 - else - param_name = param[:name] - end - # Collect all the possible types from the object. If no such type - # exists for this parameter name don't do anything. - possible_types = object.type_info.map { - |sig| sig[param_name] or nil - }.compact - - # If no possible types could be determined, put the type down as - # Unknown - if possible_types == [] - result << "(" << "Unknown" << ")" - else - result << "(" << "" << possible_types.join(", ") << "" << ")" - end - # Give up. It can probably be anything. - elsif not (param[:puppet_3_func] or param[:puppet_type]) - result << "(Unknown)" - end - if param[:puppet_type] and param[:parameter] - result << "(Parameter) " - elsif param[:puppet_type] and param[:property] - result << "(Property) " - end - - if param[:namevar] - result << "(Namevar) " - end - if param[:default] - result << " Default value: " << param[:default] << " " - end - - result << "" - - # This is only relevant for manifests, not puppet functions - # This is due to the fact that the scope of a parameter (as illustrated by - # by it's fully qualified name) is not relevant for the parameters in puppet - # functions, but may be for components of a manifest (i.e. classes) - unless param[:fq_name].nil? - result << " => #{param[:fq_name]}" - end - - if param[:desc] - result << " -

    #{param[:desc]}

    " - end - - if !param[:exists?] - result << "
    " - end - - if param[:allowed_values] and param[:allowed_values] != [] - result << "\n Allowed Values: " - result << "
      " - param[:allowed_values].each do |value_thing| - result << "
    • " - result << "" << value_thing.first << "" - if value_thing[1] - result << " only available if " << "" << value_thing[1] << "" - end - result << "
    • " - end - result << "
    \n" - end - - result << "
  • " - end - - result.join - end -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb deleted file mode 100644 index 05d8aeb..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/layout/html/setup.rb +++ /dev/null @@ -1,18 +0,0 @@ -# TODO: This should be extendable. However, the re-assignment of -# @objects_by_letter prevents that. Submit a pull request. -def index - @objects_by_letter = {} - objects = Registry.all(:class, :module, :type, :puppetnamespace, :hostclass, :definedtype, :provider).sort_by {|o| o.name.to_s } - objects = run_verifier(objects) - objects.each {|o| (@objects_by_letter[o.name.to_s[0,1].upcase] ||= []) << o } - erb(:index) -end - -def menu_lists - [ - {:type => 'puppet_manifest', :title => 'Puppet Manifests', :search_title => "Puppet Manifest List"}, - {:type => 'puppet_plugin', :title => 'Puppet Plugins', :search_title => "Puppet Plugin List"}, - {:type => 'puppet_type', :title => 'Puppet Types', :search_title => "Puppet Type List"}, - {:type => 'puppet_provider', :title => 'Puppet Providers', :search_title => "Puppet Provider List"}, - ] + super -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb deleted file mode 100644 index 1ca030b..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/html/header.erb +++ /dev/null @@ -1,17 +0,0 @@ -

    Method: <%= object.path %>

    -
    -
    -
    Defined in:
    -
    - <%= object.file %><% if object.files.size > 1 %>,
    - <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    - <% end %> - - - - -
    -
    - <%= yieldall :index => 0 %> -
    -
    \ No newline at end of file diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb deleted file mode 100644 index 4ab00b6..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/setup.rb +++ /dev/null @@ -1,21 +0,0 @@ -include T('default/module') -require File.join(File.dirname(__FILE__),'../html_helper') -require File.join(File.dirname(__FILE__),'../template_helper') - -def init - sections :header, [:method_signature, T('docstring'), :source] - parents = YARD::Registry.all(:method).reject do |item| - item.name == object.name and item.namespace === PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject - end - if parents.length == 0 - @template_helper = TemplateHelper.new - @template_helper.check_parameters_match_docs object - end -end - -def source - return if owner != object.namespace - return if Tags::OverloadTag === object - return if object.source.nil? - erb(:source) -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb deleted file mode 100644 index e0429b1..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/method_details/text/header.erb +++ /dev/null @@ -1,2 +0,0 @@ -<%= yieldall %> - diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb deleted file mode 100644 index 6e9bf56..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/command_details.erb +++ /dev/null @@ -1,8 +0,0 @@ -

    Commands Summary

    -
    -
      - <% @command_details.each do |command| %> -
    • <%= command %>
    • - <% end %> -
    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb deleted file mode 100644 index fa7b88d..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/confine_details.erb +++ /dev/null @@ -1,10 +0,0 @@ -

    Confines

    -<% if @confine_details != {} %> -
    -
      - <% @confine_details.each_pair do |key, value| %> -
    • <%= key %> - <%= value %>
    • - <% end %> -
    -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb deleted file mode 100644 index cc71ded..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/default_details.erb +++ /dev/null @@ -1,10 +0,0 @@ -

    Defaults

    -<% if @default_details != {} %> -
    -
      - <% @default_details.each_pair do |key, value| %> -
    • <%= key %> - <%= value %>
    • - <% end %> -
    -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb deleted file mode 100644 index da20e29..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/docstring.erb +++ /dev/null @@ -1,34 +0,0 @@ -
    -
    -

    <%= htmlify(Puppet::Util::Docs::scrub(@class_details[:desc])) %>

    -
    -
    -
    - <% if @class_details[:examples] != {}%> -
    -

    Examples:

    - <% @class_details[:examples].each do |title, text| %> -

    <%= title %>

    -
    <%= text %>
    - <% end %> -
    - <% end %> - <% if @class_details[:since] %> -

    Since:

    -
      -
    • -
      -

      <%= @class_details[:since] %>

      -
      -
    • -
    - <% end %> - <% if @class_details[:return] %> -

    Return:

    -
      -
    • - <%= @html_helper.generate_return_types(@class_details[:return][1], @class_details[:return][0]) %> -
    • -
    - <% end %> -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb deleted file mode 100644 index 6ebfcff..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/feature_details.erb +++ /dev/null @@ -1,10 +0,0 @@ -

    Features

    -<% if @feature_details != [] %> -
    -
      - <% @feature_details.each do |feature| %> -
    • <%= feature %>
    • - <% end %> -
    -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb deleted file mode 100644 index 74b3dba..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/header.erb +++ /dev/null @@ -1,5 +0,0 @@ -
    -

    - <%= @header_text %> -

    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb deleted file mode 100644 index 91e114a..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/html/setup.rb +++ /dev/null @@ -1 +0,0 @@ -include T('default/module/html') diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb deleted file mode 100644 index 8acd72d..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/provider/setup.rb +++ /dev/null @@ -1,50 +0,0 @@ -include T('default/module') - -require File.join(File.dirname(__FILE__),'../html_helper') -require File.join(File.dirname(__FILE__),'../template_helper') - -def init - sections :header, :box_info, :pre_docstring, :docstring, :command_details, :confine_details, :default_details, :feature_details - - @template_helper = TemplateHelper.new - @html_helper = HTMLHelper.new -end - -def header - @header_text = object.header_name - - erb(:header) -end - -def command_details - @command_details = object.commands - erb(:command_details) -end - -def confine_details - @confine_details = object.confines - erb(:confine_details) -end - -def default_details - @default_details = object.defaults - erb(:default_details) -end - -def feature_details - @feature_details = object.features - erb(:feature_details) -end - -def header - @header_text = "Puppet Provider: #{object.name}" - - erb(:header) -end - -def docstring - - @class_details = @template_helper.extract_tag_data(object) - - erb(:docstring) -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb deleted file mode 100644 index 1780c32..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/box_info.erb +++ /dev/null @@ -1,11 +0,0 @@ -
    -
    Defined in:
    -
    - <% @source_files.each do |file| %> - <%= file[0] %>: - <%= file[1] %> -
    - <% end %> -
    -
    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb deleted file mode 100644 index 74b3dba..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/header.erb +++ /dev/null @@ -1,5 +0,0 @@ -
    -

    - <%= @header_text %> -

    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb deleted file mode 100644 index b793a24..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_details_list.erb +++ /dev/null @@ -1,53 +0,0 @@ -

    Function Details

    -<% @class_details.each do |func| %> -

    > - - <% if func[:return] %> - <%= @html_helper.generate_return_types(func[:return][1]) %> - <% end %> - <%= func[:name] %> - -

    -
    -
    -

    <%= htmlify(func[:desc]) %>

    -
    -
    -
    - <% if func[:examples] != {}%> -
    -

    Examples:

    - <% func[:examples].each do |title, text| %> -

    <%= title %>

    -
    <%= text %>
    - <% end %> -
    - <% end %> - <% if func[:since] %> -

    Since:

    -
      -
    • -
      -

      <%= func[:since] %>

      -
      -
    • -
    - <% end %> - <% if func[:return] %> -

    Returns:

    -
      -
    • - <%= @html_helper.generate_return_types(func[:return][1], func[:return][0]) %> -
    • -
    - <% end %> - <% if func[:params] != nil %> -

    Parameters:

    -
    -
      - <%= @html_helper.generate_parameters(func[:params], object.child) %> -
    -
    - <% end %> -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb deleted file mode 100644 index 11ec619..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/method_summary.erb +++ /dev/null @@ -1,20 +0,0 @@ -

    Available Functions

    - diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb deleted file mode 100644 index 91e114a..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/html/setup.rb +++ /dev/null @@ -1 +0,0 @@ -include T('default/module/html') diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb deleted file mode 100644 index e1e174a..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/puppetnamespace/setup.rb +++ /dev/null @@ -1,91 +0,0 @@ -include T('default/module') - -require File.join(File.dirname(__FILE__),'../html_helper') -require File.join(File.dirname(__FILE__),'../template_helper') - -def init - sections :header, :box_info, - :method_summary, [:item_summary], - :method_details_list, [T('method_details')] - - @methods = object.children - @template_helper = TemplateHelper.new -end - -def header - # The list is expected to only contain one type of function - if @methods[0]['puppet_4x_function'] - @header_text = "Puppet 4 Functions" - else - @header_text = "Puppet 3 Functions" - end - - erb(:header) -end - -def box_info - @source_files = [] - - @methods.each do |method| - # extract the file name and line number for each method - file_name = method.files[0][0] - line_number = method.files[0][1] - - @source_files.push([method.name, "#{file_name} (#{line_number})"]) - end - - erb(:box_info) -end - -def method_summary - @method_details = [] - @html_helper = HTMLHelper.new - - @methods.each do |method| - # If there are multiple sentences in the method description, only - # use the first one for the summary. If the author did not include - # any periods in their summary, include the whole thing - first_sentence = method.docstring.match(/^(.*?)\./) - brief_summary = first_sentence ? first_sentence : method.docstring - - return_tag = method.tags.find { |tag| tag.tag_name == "return"} - return_types = return_tag.nil? ? nil : return_tag.types - - @method_details.push({:name => method.name, :short_desc => brief_summary, :return_types => return_types}) - end - - erb(:method_summary) -end - -def method_details_list - @class_details = [] - @html_helper = HTMLHelper.new - - @methods.each do |object| - - method_info = @template_helper.extract_tag_data(object) - param_details = nil - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} - - if object['puppet_4x_function'] - # Extract the source code - source_code = object.source - # Extract the parameters for the source code - parameters = source_code.match(/(?:def .*)\((.*?)\)/) - # Convert the matched string into an array of strings - params = parameters.nil? ? nil : parameters[1].split(/\s*,\s*/) - - param_details = @template_helper.extract_param_details(params, param_tags) unless params.nil? - @template_helper.check_types_match_docs object, param_details - @template_helper.check_parameters_match_docs object - else - param_details = @template_helper.comment_only_param_details(param_tags) - end - - method_info[:params] = param_details - - @class_details.push(method_info) - end - - erb(:method_details_list) -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb b/lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb deleted file mode 100644 index fab415b..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/template_helper.rb +++ /dev/null @@ -1,192 +0,0 @@ -require "puppet" - -# A class containing helper methods to aid in the extraction of relevant data -# from comments and YARD tags -class TemplateHelper - # Extracts data from comments which include the supported YARD tags - def extract_tag_data(object) - examples = Hash.new - example_tags = object.tags.find_all { |tag| tag.tag_name == "example" } - example_tags.each do |example| - examples["#{example.name}"] = example.text - end - - return_tag = object.tags.find { |tag| tag.tag_name == "return"} - return_text = return_tag.nil? ? nil : return_tag.text - return_types = return_tag.nil? ? nil : return_tag.types - return_details = (return_text.nil? && return_types.nil?) ? nil : [return_text, return_types] - - since_tag = object.tags.find { |tag| tag.tag_name == "since"} - since_text = since_tag.nil? ? nil : since_tag.text - - {:name => object.name, :desc => object.docstring, :examples => examples, :since => since_text, :return => return_details} - end - - # Given the parameter information and YARD param tags, extracts the - # useful information and returns it as an array of hashes which can - # be printed and formatted as HTML - # - # @param parameters [Array] parameter details obtained programmatically - # @param tags_hash [Array] parameter details obtained from comments - # @param fq_name [Boolean] does this parameter have a fully qualified name? - # - # @return [Hash] The relevant information about each parameter with the following keys/values: - # {:name => [String] The name of the parameter - # :fq_name => [String] The fully qualified parameter name - # :desc => [String] The description provided in the comment - # :types => [Array] The parameter type(s) specified in the comment - # :exists => [Boolean] True only if the parameter exists in the documented logic and not just in a comment} - def extract_param_details(parameters, tags_hash, fq_name = false) - parameter_info = [] - - # Extract the information for parameters that exist - # as opposed to parameters that are defined only in the comments - parameters.each do |param| - if fq_name - param_name = param[0] - fully_qualified_name = param[1] - else - param_name = param - end - - param_tag = tags_hash.find { |tag| tag.name == param_name } - - description = param_tag.nil? ? nil : param_tag.text - param_types = param_tag.nil? ? nil : param_tag.types - - param_details = {:name => param_name, :desc => description, :types => param_types, :exists? => true} - - if fq_name - param_details[:fq_name] = fully_qualified_name - end - - parameter_info.push(param_details) - end - - # Check if there were any comments for parameters that do not exist - tags_hash.each do |tag| - param_exists = false - parameter_info.each do |parameter| - if parameter[:name] == tag.name - param_exists = true - end - end - if !param_exists - parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => false}) - end - end - - parameter_info - end - - # Generates parameter information in situations where the information can only - # come from YARD tags in the comments, not from the code itself. For now the only - # use for this is 3x functions. In this case exists? will always be true since we - # cannot verify if the parameter exists in the code itself. We must trust the user - # to provide information in the comments that is accurate. - # - # @param param_tags [Array] parameter details obtained from comments - # - # @return [Hash] The relevant information about each parameter with the following keys/values: - # {:name => [String] The name of the parameter - # :desc => [String] The description provided in the comment - # :types => [Array] The parameter type(s) specified in the comment - # :exists => [Boolean] True only if the parameter exists in the documented logic and not just in a comment - # :puppet_3_func => [Boolean] Are these parameters for a puppet 3 function? (relevant in HTML generation)} - def comment_only_param_details(param_tags) - return if param_tags.empty? - - parameter_info = [] - - param_tags.each do |tag| - parameter_info.push({:name => tag.name, :desc => tag.text, :types => tag.types, :exists? => true, :puppet_3_func => true}) - end - - parameter_info - end - - # Check that any types specified in the docstrings match the actual method - # types. This is used by puppet 4x functions and defined types. - # @param object the code object to examine for parameters names - def check_types_match_docs(object, params_hash) - # We'll need this to extract type info from the type specified by the - # docstring. - type_parser = Puppet::Pops::Types::TypeParser.new - type_calculator = Puppet::Pops::Types::TypeCalculator.new - - object.type_info.each do |function| - function.keys.each do |key| - if function[key].class == String - begin - instantiated = type_parser.parse function[key] - rescue Puppet::ParseError - # Likely the result of a malformed type - next - end - else - instantiated = function[key] - end - params_hash.each do |param| - if param[:name] == key and param[:types] != nil - param[:types].each do |type| - param_instantiated = type_parser.parse type - if not type_calculator.assignable? instantiated, param_instantiated - actual_types = object.type_info.map do |sig| - sig[key].to_s if sig[key] - end.compact - # Get the locations where the object can be found. We only care about - # the first one. - locations = object.files - warning = <<-EOS -[warn]: @param tag types do not match the code. The #{param[:name]} - parameter is declared as types #{param[:types]} in the docstring, - but the code specifies the types #{actual_types} - EOS - - # If the locations aren't in the shape we expect then report that - # the file number couldn't be determined. - if locations.length >= 1 and locations[0].length == 2 - file = locations[0][0] - line = locations[0][1] - warning += " in the file #{file} near line #{line}." - else - warning += " Sorry, the file and line number could " + - "not be determined." - end - $stderr.puts warning - end - end - end - end - end - end - end - - # Check that the actual function parameters match what is stated in the docs. - # If there is a mismatch, print a warning to stderr. - # This is necessary for puppet classes and defined types. This type of - # warning will be issued for ruby code by the ruby docstring parser. - # @param object the code object to examine for parameters names - def check_parameters_match_docs(object) - param_tags = object.tags.find_all{ |tag| tag.tag_name == "param"} - names = object.parameters.map {|l| l.first.gsub(/\W/, '') } - locations = object.files - param_tags.each do |tag| - if not names.include?(tag.name) - if locations.length >= 1 and locations[0].length == 2 - file_name = locations[0][0] - line_number = locations[0][1] - $stderr.puts <<-EOS -[warn]: The parameter #{tag.name} is documented, but doesn't exist in - your code, in file #{file_name} near line #{line_number}. -EOS - else - $stderr.puts <<-EOS -[warn]: The parameter #{tag.name} is documented, but doesn't exist in - your code. Sorry, the file and line number could not be determined. -EOS - end - end - end - end -end diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb deleted file mode 100644 index da20e29..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/docstring.erb +++ /dev/null @@ -1,34 +0,0 @@ -
    -
    -

    <%= htmlify(Puppet::Util::Docs::scrub(@class_details[:desc])) %>

    -
    -
    -
    - <% if @class_details[:examples] != {}%> -
    -

    Examples:

    - <% @class_details[:examples].each do |title, text| %> -

    <%= title %>

    -
    <%= text %>
    - <% end %> -
    - <% end %> - <% if @class_details[:since] %> -

    Since:

    -
      -
    • -
      -

      <%= @class_details[:since] %>

      -
      -
    • -
    - <% end %> - <% if @class_details[:return] %> -

    Return:

    -
      -
    • - <%= @html_helper.generate_return_types(@class_details[:return][1], @class_details[:return][0]) %> -
    • -
    - <% end %> -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb deleted file mode 100644 index 74b3dba..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/header.erb +++ /dev/null @@ -1,5 +0,0 @@ -
    -

    - <%= @header_text %> -

    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb deleted file mode 100644 index 3d57a79..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/parameter_details.erb +++ /dev/null @@ -1,12 +0,0 @@ -

    Parameter Summary

    -
    -
      - <%= @html_helper.generate_parameters(@param_details, object) %> -
    -
    -

    Features

    -
    -
      - <%= @html_helper.generate_features(@feature_details, object) %> -
    -
    diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb deleted file mode 100644 index 779af2d..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/provider_details.erb +++ /dev/null @@ -1,10 +0,0 @@ -

    Available Providers

    -<% if @providers != [] %> -
    - -
    -<% end %> diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb deleted file mode 100644 index 91e114a..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/html/setup.rb +++ /dev/null @@ -1 +0,0 @@ -include T('default/module/html') diff --git a/lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb b/lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb deleted file mode 100644 index 016e269..0000000 --- a/lib/puppet_x/puppet/strings/yard/templates/default/type/setup.rb +++ /dev/null @@ -1,55 +0,0 @@ -include T('default/module') - -require File.join(File.dirname(__FILE__),'../html_helper') -require File.join(File.dirname(__FILE__),'../template_helper') - -def init - sections :header, :box_info, :pre_docstring, :docstring, :parameter_details, :provider_details - - @template_helper = TemplateHelper.new - @html_helper = HTMLHelper.new -end - -def header - @header_text = object.header_name - - erb(:header) -end - -def provider_details - type_name = object.name.to_s - @providers = YARD::Registry.all(:provider).select { |t| t.type_name == type_name } - - erb(:provider_details) -end - -def parameter_details - params = object.parameter_details.map { |h| h[:name] } - # Put properties and parameters in one big list where the descriptions are - # scrubbed and htmlified and the namevar is the first element, the ensure - # property the second, and the rest are alphabetized. - @param_details = (object.parameter_details + object.property_details).each { - |h| h[:desc] = htmlify(Puppet::Util::Docs::scrub(h[:desc])) if h[:desc] - }.sort { |a, b| a[:name] <=> b[:name] } - # Float ensurable and namevars to the top of the list - @param_details = @param_details.partition{|a| a[:name] == 'ensure'}.flatten - @param_details = @param_details.partition{|a| a[:namevar]}.flatten - - @feature_details = object.features - @template_helper.check_parameters_match_docs object - - erb(:parameter_details) -end - -def header - @header_text = "Puppet Type: #{object.name}" - - erb(:header) -end - -def docstring - - @class_details = @template_helper.extract_tag_data(object) - - erb(:docstring) -end diff --git a/puppet-strings.gemspec b/puppet-strings.gemspec index c0dfd7a..77c8314 100644 --- a/puppet-strings.gemspec +++ b/puppet-strings.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |s| s.files = `git ls-files`.split("\n") - Dir['.*', '*.gemspec'] s.add_runtime_dependency 'puppet', '>= 3.7.0' - s.add_runtime_dependency 'yard', '~> 0.8' + s.add_runtime_dependency 'yard', '~> 0.9.5' end diff --git a/spec/lib/strings_spec/module_helper.rb b/spec/lib/strings_spec/module_helper.rb deleted file mode 100644 index 77bc860..0000000 --- a/spec/lib/strings_spec/module_helper.rb +++ /dev/null @@ -1,20 +0,0 @@ -class PuppetModuleHelper -# Helper methods to handle file operations around generating and loading HTML - def self.using_module(path, modulename, &block) - Dir.mktmpdir do |tmp| - module_location = File.join(path, "examples", modulename) - FileUtils.cp_r(module_location, tmp) - old_dir = Dir.pwd - begin - Dir.chdir(tmp) - yield(tmp) - ensure - Dir.chdir(old_dir) - end - end - end - - def self.read_html(dir, modulename, file) - File.read(File.join(dir, modulename, 'doc', file)) - end -end diff --git a/spec/lib/strings_spec/parsing.rb b/spec/lib/strings_spec/parsing.rb deleted file mode 100644 index 9d1f2b3..0000000 --- a/spec/lib/strings_spec/parsing.rb +++ /dev/null @@ -1,42 +0,0 @@ -require 'spec_helper' - -module StringsSpec - module Parsing - - # Cleans up the Registry and gives YARD some source code - # to generate documentation for - def parse(string, parser = :ruby) - YARD::Registry.clear - YARD::Parser::SourceParser.parse_string(string, parser) - end - - # A custom matcher that allows us to compare aspects of a - # Code Objects to the specified values. This gives us a - # simplified way to ensure that the Code Object added to the - # Registry is what we expect when testing handlers - RSpec::Matchers.define :document_a do |arguments| - match do |actual| - @mismatches = compare_values(actual, arguments) - @mismatches.empty? - end - - failure_message do |actual| - @mismatches.collect do |key, value| - "Expected #{key} to be <#{value[1]}>, but got <#{value[0]}>." - end.join("\n") - end - - def compare_values(actual, expected) - mismatched_arguments = {} - expected.each do |key, value| - actual_value = actual.send(key) - if actual_value != value - mismatched_arguments[key] = [actual_value, value] - end - end - mismatched_arguments - end - end - end -end - diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 0546365..bf10b10 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,7 @@ require 'mocha' require 'puppet' require 'rspec' -require 'puppet_x/puppet/strings' +require 'puppet-strings' RSpec.configure do |config| config.mock_with :mocha diff --git a/spec/unit/puppet/examples/test/lib/puppet/functions/4x_function.rb b/spec/unit/puppet/examples/test/lib/puppet/functions/4x_function.rb deleted file mode 100644 index 5825496..0000000 --- a/spec/unit/puppet/examples/test/lib/puppet/functions/4x_function.rb +++ /dev/null @@ -1,5 +0,0 @@ -# function 4x -# -# This is a function which is used to test puppet strings -Puppet::Functions.create_function(:function4x) do -end diff --git a/spec/unit/puppet/examples/test/lib/puppet/parser/functions/function3x.rb b/spec/unit/puppet/examples/test/lib/puppet/parser/functions/function3x.rb deleted file mode 100644 index e3083ea..0000000 --- a/spec/unit/puppet/examples/test/lib/puppet/parser/functions/function3x.rb +++ /dev/null @@ -1,3 +0,0 @@ -Puppet::Parser::Functions.newfunction(:function3x, :doc => "This is the -function documentation for `function3x`") do |args| -end diff --git a/spec/unit/puppet/examples/test/manifests/init.pp b/spec/unit/puppet/examples/test/manifests/init.pp deleted file mode 100644 index 8ebd451..0000000 --- a/spec/unit/puppet/examples/test/manifests/init.pp +++ /dev/null @@ -1,27 +0,0 @@ -# Class: test -# -# This class exists to serve as fixture data for testing the puppet strings face -# -# @example -# class { "test": } -# -# @param package_name The name of the package -# @param service_name The name of the service -class test ( - $package_name = $test::params::package_name, - $service_name = $test::params::service_name, - -) inherits test::params { - - # validate parameters here - - class { 'test::install': } -> - class { 'test::config': } ~> - class { 'test::service': } -> - Class['test'] - - File { - owner => 'user', - path => 'some/file/path', - } -} diff --git a/spec/unit/puppet/examples/test/manifests/triple_nested_classes.pp b/spec/unit/puppet/examples/test/manifests/triple_nested_classes.pp deleted file mode 100644 index 6ac95cd..0000000 --- a/spec/unit/puppet/examples/test/manifests/triple_nested_classes.pp +++ /dev/null @@ -1,27 +0,0 @@ -# Testing tested classes -# docs stuff -# @param nameservers [String] Don't ask me what this does! -# @param default_lease_time [Integer[1024, 8192]] text goes here -# @param max_lease_time does stuff -class outer ( - $dnsdomain, - $nameservers, - $default_lease_time = 3600, - $max_lease_time = 86400 - ) { - # @param options [String[5,7]] gives user choices - # @param multicast [Boolean] foobar - # @param servers yep, that's right - class middle ( - $options = "iburst", - $servers, - $multicast = false - ) { - class inner ( - $choices = "uburst", - $secenekler = "weallburst", - $boxen, - $manyspell = true - ) {} - } -} diff --git a/spec/unit/puppet/examples/test/metadata.json b/spec/unit/puppet/examples/test/metadata.json deleted file mode 100644 index 1892d9d..0000000 --- a/spec/unit/puppet/examples/test/metadata.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "username-test", - "version": "0.0.1", - "author": "username", - "license": "Apache 2.0" -} diff --git a/spec/unit/puppet/face_spec.rb b/spec/unit/puppet/face_spec.rb deleted file mode 100644 index f08e013..0000000 --- a/spec/unit/puppet/face_spec.rb +++ /dev/null @@ -1,132 +0,0 @@ -require 'spec_helper' -require 'lib/strings_spec/module_helper' -require 'puppet/face/strings' -require 'tmpdir' -require 'stringio' - -describe Puppet::Face do - - describe "YARDoc action" do - it "should raise an error if yard is absent" do - Puppet.features.stubs(:yard?).returns(false) - expect{Puppet::Face[:strings, :current].yardoc}.to raise_error(RuntimeError, "The 'yard' gem must be installed in order to use this face.") - end - - it "should raise an error if rgen is absent" do - Puppet.features.stubs(:rgen?).returns(false) - expect{Puppet::Face[:strings, :current].yardoc}.to raise_error(RuntimeError, "The 'rgen' gem must be installed in order to use this face.") - end - - it "should raise an error if the Ruby verion is less than 1.9", :if => RUBY_VERSION.match(/^1\.8/) do - expect{Puppet::Face[:strings, :current].yardoc}.to raise_error(RuntimeError, "This face requires Ruby 1.9 or greater.") - end - - it "should invoke Yardoc with MODULE_SOURCEFILES if no arguments are provided" do - YARD::CLI::Yardoc.expects(:run).with('manifests/**/*.pp', 'lib/**/*.rb') - Puppet::Face[:strings, :current].yardoc - end - - it "should invoke Yardoc with provided arguments" do - YARD::CLI::Yardoc.expects(:run).with('--debug', 'some_file.rb') - Puppet::Face[:strings, :current].yardoc('--debug', 'some_file.rb') - end - - describe "when generating HTML for documentation" do - - # HACK: In these tests we would like to suppress all output from the yard - # logger so we don't clutter up stdout. - # However, we do want the yard logger for other tests so we can - # assert that the right things are logged. To accomplish this, for - # this block of tests we monkeypatch the yard logger to be a generic - # stringio instance which does nothing and then we restore the - # original afterwards. - before(:all) do - @tmp = YARD::Logger.instance.io - YARD::Logger.instance.io = StringIO.new - end - - after(:all) do - YARD::Logger.instance.io = @tmp - end - - it "should properly generate HTML for manifest comments" do - - - PuppetModuleHelper.using_module(File.dirname(__FILE__), 'test') do |tmp| - Dir.chdir('test') - - Puppet::Face[:strings, :current].yardoc - - expect(PuppetModuleHelper.read_html(tmp, 'test', 'test.html')).to include("Class: test") - end - end - - it "should properly generate HTML for 3x function comments" do - PuppetModuleHelper.using_module(File.dirname(__FILE__), 'test') do |tmp| - Dir.chdir('test') - - Puppet::Face[:strings, :current].yardoc - - expect(PuppetModuleHelper.read_html(tmp, 'test', 'Puppet3xFunctions.html')).to include("This is the function documentation for `function3x`") - end - end - - it "should properly generate HTML for 4x function comments" do - PuppetModuleHelper.using_module(File.dirname(__FILE__), 'test') do |tmp| - Dir.chdir('test') - - Puppet::Face[:strings, :current].yardoc - - expect(PuppetModuleHelper.read_html(tmp, 'test', 'Puppet4xFunctions.html')).to include("This is a function which is used to test puppet strings") - end - end - - it "should create correct files for nested classes" do - PuppetModuleHelper.using_module(File.dirname(__FILE__), 'test') do |tmp| - Dir.chdir('test') - - Puppet::Face[:strings, :current].yardoc - - expect(PuppetModuleHelper.read_html(tmp, - 'test', 'outer.html')).to include("Puppet Class: outer") - expect(PuppetModuleHelper.read_html(tmp, 'test', - 'outer/middle.html')).to include("Puppet Class: middle") - expect(PuppetModuleHelper.read_html(tmp, 'test', - 'outer/middle/inner.html')).to include("Puppet Class: inner") - end - end - - it "should create proper namespace for nested classes" do - PuppetModuleHelper.using_module(File.dirname(__FILE__), 'test') do |tmp| - Dir.chdir('test') - - Puppet::Face[:strings, :current].yardoc - - expect(PuppetModuleHelper.read_html(tmp, - 'test', 'outer.html')).to include("Hostclass: outer") - expect(PuppetModuleHelper.read_html(tmp, 'test', - 'outer/middle.html')).to include("Hostclass: outer::middle") - expect(PuppetModuleHelper.read_html(tmp, 'test', - 'outer/middle/inner.html')).to include("Hostclass: outer::middle::inner") - end - end - end - end - - describe "server action" do - it "should raise an error if yard is absent" do - Puppet.features.stubs(:yard?).returns(false) - expect{Puppet::Face[:strings, :current].server}.to raise_error(RuntimeError, "The 'yard' gem must be installed in order to use this face.") - end - - it "should raise an error if rgen is absent" do - Puppet.features.stubs(:rgen?).returns(false) - expect{Puppet::Face[:strings, :current].server}.to raise_error(RuntimeError, "The 'rgen' gem must be installed in order to use this face.") - end - - it "should raise an error if the Ruby version is less than 1.9", :if => RUBY_VERSION.match(/^1\.8/) do - expect{Puppet::Face[:strings, :current].server}.to raise_error(RuntimeError, "This face requires Ruby 1.9 or greater.") - end - end -end - diff --git a/spec/unit/puppet_x/puppet/strings/pops_spec.rb b/spec/unit/puppet_x/puppet/strings/pops_spec.rb deleted file mode 100644 index 8a440e1..0000000 --- a/spec/unit/puppet_x/puppet/strings/pops_spec.rb +++ /dev/null @@ -1,38 +0,0 @@ -require 'spec_helper' -require 'puppet_x/puppet/strings/pops/yard_statement' - -describe PuppetX::Puppet::Strings::Pops do - let(:parser) {Puppet::Pops::Parser::Parser.new()} - - describe "YARDstatement class" do - let(:manifest) {"#hello world\nclass foo { }"} - let(:model) {parser.parse_string(manifest).current.definitions.first} - let(:test_statement) {PuppetX::Puppet::Strings::Pops::YARDStatement.new(model)} - - describe "when creating a new instance of YARDStatement" do - it "should extract comments from the source code" do - expect(test_statement.comments).to match(/^#hello world/) - end - end - end - - describe "YARDTransfomer class" do - let(:manifest) {"#hello world\nclass foo($bar) { }"} - let(:manifest_default) {"#hello world\nclass foo($bar = 3) { }"} - let(:transformer) {PuppetX::Puppet::Strings::Pops::YARDTransformer.new} - - describe "transform method" do - it "should perform the correct transformation with parameter defaults" do - model = parser.parse_string(manifest_default).current.definitions.first - statements = transformer.transform(model) - expect(statements.parameters[0][0].class).to be(PuppetX::Puppet::Strings::Pops::YARDStatement) - end - - it "should perform the correct transofmration without parameter defaults" do - model = parser.parse_string(manifest).current.definitions.first - statements = transformer.transform(model) - expect(statements.parameters[0][1].class).to be(NilClass) - end - end - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb deleted file mode 100644 index 6f3bd76..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/defined_type_handler_spec.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'spec_helper' -require 'puppet_x/puppet/strings/yard/handlers/defined_type_handler' -require 'strings_spec/parsing' - - -describe PuppetX::Puppet::Strings::YARD::Handlers::DefinedTypeHandler do - include StringsSpec::Parsing - - def the_definedtype() - YARD::Registry.at("foo::bar") - end - - it "should parse single-line documentation strings before a given defined type" do - comment = "Definition: foo::bar" - puppet_code = <<-PUPPET - # #{comment} - define foo::bar ($baz) { } - PUPPET - - parse(puppet_code, :puppet) - - expect(the_definedtype).to document_a(:type => :definedtype, :docstring => comment) - end - - it "should parse multi-line documentation strings before a given defined type" do - puppet_code = <<-PUPPET - # Definition: foo::bar - # - # This class does some stuff - define foo::bar ($baz) { } - PUPPET - - parse(puppet_code, :puppet) - - comment = "Definition: foo::bar\n\nThis class does some stuff" - expect(the_definedtype).to document_a(:type => :definedtype, :docstring => comment) - end - - it "should not parse documentation before a function if it is followed by a new line" do - puppet_code = <<-PUPPET - # Definition: foo::bar - - define foo::bar ($baz) { } - PUPPET - - parse(puppet_code, :puppet) - - expect(the_definedtype).to document_a(:type => :definedtype, :docstring => "") - end - - it "should not add anything to the Registry if incorrect puppet code is present" do - puppet_code = <<-PUPPET - # Definition: foo::bar - This is not puppet code - PUPPET - - parse(puppet_code, :puppet) - - expect(YARD::Registry.all).to be_empty - end - - it "should generate the correct namespace " do - puppet_code = <<-PUPPET - define puppet_enterprise::mcollective::client::certs { } - PUPPET - - parse(puppet_code, :puppet) - # If the namespace is not correctly generated, we will not be able to find the - # object via this name, meaning namespace will be nil - namespace = YARD::Registry.at("puppet_enterprise::mcollective::client::certs").namespace.to_s - - expect(namespace).to_not be_nil - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb deleted file mode 100644 index 4fc372c..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-dispatch/lib/test.rb +++ /dev/null @@ -1,18 +0,0 @@ -# @param not_a_param [Integer] the first number to be compared -# @param also_not_a_param [Integer] the second number to be compared -Puppet::Functions.create_function(:max) do - dispatch max_1 do - param 'Integer[1,2]', :num_a - param 'Integer', :num_b - end - dispatch max_2 { - param 'String', :num_c - param 'String[1,2]', :num_d - } - def max_1(num_a, num_b) - num_a >= num_b ? num_a : num_b - end - def max_2(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb deleted file mode 100644 index 22cb89c..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ-with-types/lib/test.rb +++ /dev/null @@ -1,7 +0,0 @@ -# @param not_a_param [Integer[1,2]] the first number to be compared -# @param also_not_a_param [Integer[1,2]] the second number to be compared -Puppet::Functions.create_function(:max) do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb deleted file mode 100644 index cf46559..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-differ/lib/test.rb +++ /dev/null @@ -1,7 +0,0 @@ -# @param not_a_param [Integer] the first number to be compared -# @param also_not_a_param [Integer] the second number to be compared -Puppet::Functions.create_function(:max) do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb deleted file mode 100644 index 6e7342c..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-dispatch/lib/test.rb +++ /dev/null @@ -1,11 +0,0 @@ -# @param [Integer] num_a the first number to be compared -# @param num_b [Integer] the second number to be compared -Puppet::Functions.create_function(:max) do - dispatch max_1 do - param 'Integer', :num_a - param 'Integer', :num_b - end - def max_1(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb deleted file mode 100644 index fc5e92a..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match-with-types/lib/test.rb +++ /dev/null @@ -1,7 +0,0 @@ -# @param num_a [Integer[1,2]] the first number to be compared -# @param num_b [Integer[1,2]] the second number to be compared -Puppet::Functions.create_function(:max)do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb b/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb deleted file mode 100644 index 1497270..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test-param-names-match/lib/test.rb +++ /dev/null @@ -1,7 +0,0 @@ -# @param num_a [Integer] the first number to be compared -# @param num_b [Integer] the second number to be compared -Puppet::Functions.create_function(:max)do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp b/spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp deleted file mode 100644 index 7d1a8ee..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/examples/test/manifests/init.pp +++ /dev/null @@ -1,7 +0,0 @@ -# @param [Float] ident identification -class foo( String $ident = "Bob" , Integer $age = 10, ) -{ - notify {'$ident':} - notify {'$age':} -} - diff --git a/spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb deleted file mode 100644 index ea0959c..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/host_class_handler_spec.rb +++ /dev/null @@ -1,93 +0,0 @@ -require 'spec_helper' -require 'lib/strings_spec/module_helper' -require 'puppet/face/strings' -require 'puppet_x/puppet/strings/yard/handlers/host_class_handler' -require 'strings_spec/parsing' - -describe PuppetX::Puppet::Strings::YARD::Handlers::HostClassHandler do - include StringsSpec::Parsing - - def the_hostclass() - YARD::Registry.at("foo::bar") - end - - it "should parse single-line documentation strings before a given class" do - comment = "Class: foo::bar" - puppet_code = <<-PUPPET - # #{comment} - class foo::bar { } - PUPPET - - parse(puppet_code, :puppet) - - expect(the_hostclass).to document_a(:type => :hostclass, :docstring => comment) - end - - it "should parse multi-line documentation strings before a given class" do - puppet_code = <<-PUPPET - # Class: foo::bar - # - # This class does some stuff - class foo::bar { } - PUPPET - - parse(puppet_code, :puppet) - - comment = "Class: foo::bar\n\nThis class does some stuff" - expect(the_hostclass).to document_a(:type => :hostclass, :docstring => comment) - end - - it "should not parse documentation before a class if it is followed by a new line" do - puppet_code = <<-PUPPET - # Class: foo::bar - - class foo::bar { } - PUPPET - - parse(puppet_code, :puppet) - - expect(the_hostclass).to document_a(:type => :hostclass, :docstring => "") - end - - it "should generate the correct namespace " do - puppet_code = <<-PUPPET - class puppet_enterprise::mcollective::client::certs { } - PUPPET - - parse(puppet_code, :puppet) - # If the namespace is not correctly generated, we will not be able to find the - # object via this name, meaning namespace will be nil - namespace = YARD::Registry.at("puppet_enterprise::mcollective::client::certs") - - expect(namespace).to_not be_nil - end - it "should not issue just one warning if the parameter types don't match." do - YARD::Registry.clear - # FIXME The type information here will change with the next version of - # puppet. `expected` is the output expected from the stable branch. The - # output from the master branch will use this instead: - # "...specifies the types [String] in file..." - expected_stout = <<-output -Files: 1 -Modules: 0 ( 0 undocumented) -Classes: 0 ( 0 undocumented) -Constants: 0 ( 0 undocumented) -Methods: 0 ( 0 undocumented) -Puppet Classes: 1 ( 0 undocumented) -Puppet Defined Types: 0 ( 0 undocumented) -Puppet Types: 0 ( 0 undocumented) -Puppet Providers: 0 ( 0 undocumented) - 100.00% documented - output - expected_stderr = "[warn]: @param tag types do not match the code. The ident\n parameter is declared as types [\"Float\"] in the docstring,\n but the code specifies the types [\"String\"]\n in the file manifests/init.pp near line 2.\n" - - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test') do |tmp| - Dir.chdir('test') - Puppet::Face[:strings, :current].yardoc - end - }.to output(expected_stderr).to_stderr_from_any_process - }.to output(expected_stout).to_stdout_from_any_process - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb deleted file mode 100644 index d53c82d..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/puppet_3x_function_handler_spec.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'spec_helper' -require 'puppet_x/puppet/strings/yard/handlers/puppet_3x_function_handler' -require 'strings_spec/parsing' - -describe PuppetX::Puppet::Strings::YARD::Handlers::Puppet3xFunctionHandler do - include StringsSpec::Parsing - - def the_method() - YARD::Registry.at("Puppet3xFunctions#the_function") - end - - def the_namespace() - YARD::Registry.at("Puppet3xFunctions") - end - - it "should parse single-line documentation strings before a given function" do - comment = "The summary" - parse <<-RUBY - # #{comment} - newfunction(:the_function, :type => rvalue) do |args| - end - RUBY - - expect(the_method).to document_a(:type => :method, :docstring => comment) - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should parse multi-line documentation strings before a given function" do - parse <<-RUBY - # The summary - # - # The longer description - newfunction(:the_function, :type => rvalue) do |args| - end - RUBY - - comment = "The summary\n\nThe longer description" - expect(the_method).to document_a(:type => :method, :docstring => comment) - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should not parse documentation before a function if it is followed by two new lines" do - parse <<-RUBY - # The summary - - - newfunction(:the_function, :type => rvalue) do |args| - end - RUBY - - expect(the_method).to document_a(:type => :method, :docstring => "") - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should process documentation if only one option is passed to newfunction" do - parse <<-RUBY - newfunction(:the_functiion) do |args| - end - RUBY - - expect(the_namespace).to document_a(:type => :puppetnamespace) - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb deleted file mode 100644 index e1b4e54..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/puppet_4x_function_handler_spec.rb +++ /dev/null @@ -1,150 +0,0 @@ -require 'spec_helper' -require 'lib/strings_spec/module_helper' -require 'puppet_x/puppet/strings/yard/handlers/puppet_4x_function_handler' -require 'puppet/face/strings' -require 'strings_spec/parsing' - -describe PuppetX::Puppet::Strings::YARD::Handlers::Puppet4xFunctionHandler do - include StringsSpec::Parsing - - def the_method() - YARD::Registry.at("Puppet4xFunctions#the_function") - end - - def the_namespace() - YARD::Registry.at("Puppet4xFunctions") - end - - it "should parse single-line documentation strings before a given function" do - comment = "The summary" - parse <<-RUBY - # #{comment} - Puppet::Functions.create_function(:the_function) do - end - RUBY - - expect(the_method).to document_a(:type => :method, :docstring => comment) - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should parse multi-line documentation strings before a given function" do - parse <<-RUBY - # The summary - # - # The longer description - Puppet::Functions.create_function(:the_function) do - end - RUBY - - comment = "The summary\n\nThe longer description" - expect(the_method).to document_a(:type => :method, :docstring => comment) - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should not parse documentation before a function if it is followed by two new lines" do - parse <<-RUBY - # The summary - # - # The longer description - - - Puppet::Functions.create_function(:the_function) do - end - RUBY - - expect(the_method).to document_a(:type => :method, :docstring => "") - expect(the_namespace).to document_a(:type => :puppetnamespace) - end - - it "should issue a warning if the parameter names do not match the docstring" do - expected_output_not_a_param = "[warn]: The parameter not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expected_output_also_not_a_param = "[warn]: The parameter also_not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-differ') do |tmp| - Dir.chdir('test-param-names-differ') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output("#{expected_output_not_a_param}\n#{expected_output_also_not_a_param}\n").to_stderr_from_any_process - end - - it "should not issue a warning when the parameter names match the docstring" do - expected = "" - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-match') do |tmp| - Dir.chdir('test-param-names-match') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output(expected).to_stderr_from_any_process - - end - it "should not issue a warning when there are parametarized types and parameter names are the same" do - expected = "" - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-match-with-types') do |tmp| - Dir.chdir('test-param-names-match-with-types') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output(expected).to_stderr_from_any_process - end - - it "should issue a warning when there are parametarized types and parameter names differ" do - expected_output_not_num_a = "[warn]: @param tag has unknown parameter" + - " name: not_num_a \n in file `(stdin)' near line 3." - expected_output_not_a_param = "[warn]: The parameter not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expected_output_also_not_a_param = "[warn]: The parameter also_not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-differ-with-types') do |tmp| - Dir.chdir('test-param-names-differ-with-types') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output("#{expected_output_not_a_param}\n#{expected_output_also_not_a_param}\n").to_stderr_from_any_process - end - - - it "should issue a warning if the parameter names do not match the docstring in dispatch method" do - expected_output_not_a_param = "[warn]: The parameter not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expected_output_also_not_a_param = "[warn]: The parameter also_not_a_param is documented, but doesn't exist in\n your code, in file lib/test.rb near line 3." - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-differ-with-dispatch') do |tmp| - Dir.chdir('test-param-names-differ-with-dispatch') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output("#{expected_output_not_a_param}\n#{expected_output_also_not_a_param}\n").to_stderr_from_any_process - end - - it "should not issue a warning if the parameter names do match the " + - "docstring in dispatch method" do - expected = "" - expect { - expect { - PuppetModuleHelper.using_module(File.dirname(__FILE__),'test-param-names-match-with-dispatch') do |tmp| - Dir.chdir('test-param-names-match-with-dispatch') - Puppet::Face[:strings, :current].yardoc - end - }.to output(/documented/).to_stdout_from_any_process - }.to output(expected).to_stderr_from_any_process - end - - it "should parse unusually named functions" do - # This should not raise a ParseErrorWithIssue exceptoin - parse <<-RUBY - Puppet::Functions.create_function :'max' do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end - end - RUBY - end - - -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb deleted file mode 100644 index f6153a8..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/template_helper_spec.rb +++ /dev/null @@ -1,125 +0,0 @@ -require 'spec_helper' -require 'puppet_x/puppet/strings/yard/templates/default/template_helper' -require 'puppet_x/puppet/strings/yard/code_objects/puppet_namespace_object' -require 'strings_spec/parsing' - -describe TemplateHelper do - it "should not print any warning if the tags and parameters match" do - th = TemplateHelper.new - - # Case 0: If the documented tags do include the parameter, - # nothing is printed - tag0 = YARD::Tags::Tag.new(:param, 'a_parameter') - tag0.name = 'a_parameter' - obj0 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') - obj0.add_tag tag0 - obj0.parameters = [['a_parameter']] - expect { th.check_parameters_match_docs obj0 }.to output("").to_stderr_from_any_process - - # The docstring is still alive between tests. Clear the tags registered with - # it so the tags won't persist between tests. - obj0.docstring.instance_variable_set("@tags", []) - end - - it "should print the warning with no location data if the tags and " + - "parameters differ and the location data is not properly formed" do - th = TemplateHelper.new - # Case 1: If the parameter and tag differ and the location is not properly - # formed, print out the warning with no location data - tag1 = YARD::Tags::Tag.new(:param, 'aa_parameter') - tag1.name = 'aa_parameter' - obj1 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') - obj1.add_tag tag1 - obj1.parameters = [['b_parameter']] - expect { th.check_parameters_match_docs obj1 }.to output("[warn]: The parameter aa_parameter is documented, but doesn't exist in\n your code. Sorry, the file and line number could not be determined.\n").to_stderr_from_any_process - - # The docstring is still alive between tests. Clear the tags registered with - # it so the tags won't persist between tests. - obj1.docstring.instance_variable_set("@tags", []) - end - - it "should print the warning with location data if the tags and parameters " + - "differ and the location data is properly formed" do - th = TemplateHelper.new - # Case 2: If the parameter and tag differ and the location is properly - # formed, print out the warning with no location data - tag2 = YARD::Tags::Tag.new(:param, 'aaa_parameter') - tag2.name = 'aaa_parameter' - obj2 = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet3xFunctions') - obj2.files = [['some_file.pp', 42]] - obj2.add_tag tag2 - obj2.parameters = [['b_parameter']] - expect { th.check_parameters_match_docs obj2 }.to output("[warn]: The parameter aaa_parameter is documented, but doesn't exist in\n your code, in file some_file.pp near line 42.\n").to_stderr_from_any_process - - # The docstring is still alive between tests. Clear the tags registered with - # it so the tags won't persist between tests. - obj2.docstring.instance_variable_set("@tags", []) - end - - it "should issue a warning if the parameter types do not match the docstring in dispatch method" do - expected_output_not_a_param = "[warn]: @param tag types do not match the" + - " code. The arg1\n parameter is declared as types [\"Integer\"] in the " + - "docstring,\n but the code specifies the types [\"Optional[String]\"]" + - "\n in the file test near line 0.\n" - object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') - object.files = [['test', 0]] - object.type_info = [{ - 'arg0' => 'Variant[String,Array[String]]', - 'arg1' => 'Optional[String]' - }] - param_details = [{ - :name => 'arg0', - :types => ['Variant[String,Array[String]]'] - }, - { - :name => 'arg1', - :types => ['Integer'] - }] - template_helper = TemplateHelper.new - expect { - template_helper.check_types_match_docs(object, param_details) - }.to output(expected_output_not_a_param).to_stderr_from_any_process - end - - it "should not issue a warning if the parameter types do match the docstring in dispatch method" do - object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') - object.files = [['test', 0]] - object.type_info = [{ - 'arg0' => 'Variant[String,Array[String]]', - 'arg1' => 'Optional[String]' - }] - param_details = [{ - :name => 'arg0', - :types => ['Variant[String,Array[String]]'] - }, - { - :name => 'arg1', - :types => ['Optional[String]'] - }] - template_helper = TemplateHelper.new - expect { - template_helper.check_types_match_docs(object, param_details) - }.to output("").to_stderr_from_any_process - end - - it "should not issue a warning if the types in the docstring in dispatch method are assignable to parameter types" do - object = PuppetX::Puppet::Strings::YARD::CodeObjects::PuppetNamespaceObject.new(:root, 'Puppet4xFunctions') - object.files = [['test', 0]] - object.type_info = [{ - 'arg0' => 'Variant[String,Array[String]]', - 'arg1' => 'Optional[String]' - }] - param_details = [{ - :name => 'arg0', - :types => ['Variant[String,Array[String]]'] - }, - { - :name => 'arg1', - :types => ['String'] - }] - template_helper = TemplateHelper.new - expect { - template_helper.check_types_match_docs(object, param_details) - }.to output("").to_stderr_from_any_process - end -end diff --git a/spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb b/spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb deleted file mode 100644 index 72c53b1..0000000 --- a/spec/unit/puppet_x/puppet/strings/yard/type_handler_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'spec_helper' -require 'puppet_x/puppet/strings/yard/handlers/type_handler' -require 'strings_spec/parsing' - - -describe PuppetX::Puppet::Strings::YARD::Handlers::PuppetTypeHandler do - include StringsSpec::Parsing - - def the_type() - YARD::Registry.at("file") - end - - it "should have the proper docstring" do - parse <<-RUBY - Puppet::Type.newtype(:file) do - @doc = "Manages files, including their content, ownership, and perms." - newparam(:path) do - desc <<-'EOT' - The path to the file to manage. Must be fully qualified. - EOT - end - isnamevar - end - RUBY - - expect(the_type.docstring).to eq("Manages files, including their " + - "content, ownership, and perms.") - end - - it "should have the proper parameter details" do - parse <<-RUBY - Puppet::Type.newtype(:file) do - @doc = "Manages files, including their content, ownership, and perms." - newparam(:file) do - desc <<-'EOT' - The path to the file to manage. Must be fully qualified. - EOT - end - isnamevar - end - RUBY - - expect(the_type.parameter_details).to eq([{ :name => "file", - :desc => "The path to the file to manage. Must be fully qualified.", - :exists? => true, :puppet_type => true, :namevar => true, - :default => nil, - :parameter=>true, - :allowed_values=>[], - }]) - end - - it "should have the proper parameters" do - parse <<-RUBY - Puppet::Type.newtype(:file) do - @doc = "Manages files, including their content, ownership, and perms." - newparam(:path) do - desc <<-'EOT' - The path to the file to manage. Must be fully qualified. - EOT - end - isnamevar - end - RUBY - - expect(the_type.parameters).to eq([["path", nil]]) - end -end From d4bab8a5ab6160bc3399a6b8f663805104ec9bb2 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 10:58:48 -0700 Subject: [PATCH 04/15] (PDOC-63) Add initial YARD configuration. This commit adds the initial YARD configuration. Subsequent commits will integrate the code objects, handlers, parsers, tags, and templates to support Puppet code. --- lib/puppet-strings.rb | 6 +++ lib/puppet-strings/yard.rb | 54 +++++++++++++++++++++++++ lib/puppet-strings/yard/code_objects.rb | 3 ++ lib/puppet-strings/yard/handlers.rb | 3 ++ lib/puppet-strings/yard/parsers.rb | 3 ++ lib/puppet-strings/yard/tags.rb | 3 ++ 6 files changed, 72 insertions(+) create mode 100644 lib/puppet-strings/yard.rb create mode 100644 lib/puppet-strings/yard/code_objects.rb create mode 100644 lib/puppet-strings/yard/handlers.rb create mode 100644 lib/puppet-strings/yard/parsers.rb create mode 100644 lib/puppet-strings/yard/tags.rb diff --git a/lib/puppet-strings.rb b/lib/puppet-strings.rb index 0a61787..f2cbdfc 100644 --- a/lib/puppet-strings.rb +++ b/lib/puppet-strings.rb @@ -18,6 +18,9 @@ module PuppetStrings # @option options [Array] :yard_args The arguments to pass to yard. # @return [void] def self.generate(search_patterns = DEFAULT_SEARCH_PATTERNS, options = {}) + require 'puppet-strings/yard' + PuppetStrings::Yard.setup! + # Format the arguments to YARD args = ['doc'] args << '--debug' if options[:debug] @@ -51,6 +54,9 @@ module PuppetStrings # Runs the YARD documentation server. # @param [Array] args The arguments to YARD. def self.run_server(*args) + require 'puppet-strings/yard' + PuppetStrings::Yard.setup! + YARD::CLI::Server.run(*args) end end diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb new file mode 100644 index 0000000..38f2415 --- /dev/null +++ b/lib/puppet-strings/yard.rb @@ -0,0 +1,54 @@ +require 'yard' + +# Module for YARD related functionality. +module PuppetStrings::Yard + require 'puppet-strings/yard/code_objects' + require 'puppet-strings/yard/handlers' + require 'puppet-strings/yard/tags' + require 'puppet-strings/yard/parsers' + + # Sets up YARD for use with puppet-strings. + # @return [void] + def self.setup! + # Register the template path + YARD::Templates::Engine.register_template_path(File.join(File.dirname(__FILE__), 'yard', 'templates')) + end +end + +# Monkey patch YARD::CLI::Yardoc#all_objects to return our custom code objects. +# @private +class YARD::CLI::Yardoc + def all_objects + YARD::Registry.all( + :root, + :module, + :class + ) + end +end + +# Monkey patch the stats object to return statistics for our objects. +# This is the recommended way to add custom stats. +# @private +class YARD::CLI::Stats + def output(name, data, undoc = nil) + # Monkey patch output to accommodate our larger header widths + @total += data if data.is_a?(Integer) && undoc + @undocumented += undoc if undoc.is_a?(Integer) + if undoc + data = ('%5s (% 5d undocumented)' % [data, undoc]) + else + data = '%5s' % data + end + log.puts('%-21s %s' % [name + ':', data]) + end + + # This differs from the YARD implementation in that it considers + # a docstring without text but with tags to be undocumented. + def type_statistics_all(type) + objs = all_objects.select {|m| m.type == type } + undoc = objs.find_all {|m| m.docstring.all.empty? } + @undoc_list |= undoc if @undoc_list + [objs.size, undoc.size] + end +end diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb new file mode 100644 index 0000000..d346ef7 --- /dev/null +++ b/lib/puppet-strings/yard/code_objects.rb @@ -0,0 +1,3 @@ +# The module for custom YARD code objects. +module PuppetStrings::Yard::CodeObjects +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb new file mode 100644 index 0000000..e502343 --- /dev/null +++ b/lib/puppet-strings/yard/handlers.rb @@ -0,0 +1,3 @@ +# The module for custom YARD handlers. +module PuppetStrings::Yard::Handlers +end diff --git a/lib/puppet-strings/yard/parsers.rb b/lib/puppet-strings/yard/parsers.rb new file mode 100644 index 0000000..3d049d0 --- /dev/null +++ b/lib/puppet-strings/yard/parsers.rb @@ -0,0 +1,3 @@ +# The module for custom YARD parsers. +module PuppetStrings::Yard::Parsers +end diff --git a/lib/puppet-strings/yard/tags.rb b/lib/puppet-strings/yard/tags.rb new file mode 100644 index 0000000..8bd1d4b --- /dev/null +++ b/lib/puppet-strings/yard/tags.rb @@ -0,0 +1,3 @@ +# The module for custom YARD tags. +module PuppetStrings::Yard::Tags +end From f2e41a9c237f1c64b97cc7fded55062cf9054cac Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:04:17 -0700 Subject: [PATCH 05/15] (PDOC-63) Implement the Puppet parser. This commit implements the Puppet language parser that future handlers will use to generate YARD code objects for classes, defined types, and functions written in Puppet. --- lib/puppet-strings/yard.rb | 3 + lib/puppet-strings/yard/parsers.rb | 4 + .../yard/parsers/puppet/parser.rb | 70 +++++++++ .../yard/parsers/puppet/statement.rb | 146 ++++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 lib/puppet-strings/yard/parsers/puppet/parser.rb create mode 100644 lib/puppet-strings/yard/parsers/puppet/statement.rb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 38f2415..90d0be0 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -12,6 +12,9 @@ module PuppetStrings::Yard def self.setup! # Register the template path YARD::Templates::Engine.register_template_path(File.join(File.dirname(__FILE__), 'yard', 'templates')) + + # Register the Puppet parser + YARD::Parser::SourceParser.register_parser_type(:puppet, PuppetStrings::Yard::Parsers::Puppet::Parser, ['pp']) end end diff --git a/lib/puppet-strings/yard/parsers.rb b/lib/puppet-strings/yard/parsers.rb index 3d049d0..6916fee 100644 --- a/lib/puppet-strings/yard/parsers.rb +++ b/lib/puppet-strings/yard/parsers.rb @@ -1,3 +1,7 @@ # The module for custom YARD parsers. module PuppetStrings::Yard::Parsers + # The module for custom YARD parsers for the Puppet language. + module Puppet + require 'puppet-strings/yard/parsers/puppet/parser' + end end diff --git a/lib/puppet-strings/yard/parsers/puppet/parser.rb b/lib/puppet-strings/yard/parsers/puppet/parser.rb new file mode 100644 index 0000000..a74675b --- /dev/null +++ b/lib/puppet-strings/yard/parsers/puppet/parser.rb @@ -0,0 +1,70 @@ +require 'puppet' +require 'puppet/pops' +require 'puppet-strings/yard/parsers/puppet/statement' + +# Implements the Puppet language parser. +class PuppetStrings::Yard::Parsers::Puppet::Parser < YARD::Parser::Base + attr_reader :file, :source + + # Initializes the parser. + # @param [String] source The source being parsed. + # @param [String] filename The file name of the file being parsed. + # @return [void] + def initialize(source, filename) + @source = source + @file = filename + @visitor = ::Puppet::Pops::Visitor.new(self, 'transform') + end + + # Parses the source. + # @return [void] + def parse + begin + @statements ||= (@visitor.visit(::Puppet::Pops::Parser::Parser.new.parse_string(source)) || []).compact + rescue ::Puppet::ParseError => ex + log.error "Failed to parse #{@file}: #{ex.message}" + @statements = [] + end + @statements.freeze + self + end + + # Gets an enumerator for the statements that were parsed. + # @return Returns an enumerator for the statements that were parsed. + def enumerator + @statements + end + + private + def transform_Program(o) + # Cache the lines of the source text; we'll use this to locate comments + @lines = o.source_text.lines.to_a + o.definitions.map { |d| @visitor.visit(d) } + end + + def transform_Factory(o) + @visitor.visit(o.current) + end + + def transform_HostClassDefinition(o) + statement = PuppetStrings::Yard::Parsers::Puppet::ClassStatement.new(o, @file) + statement.extract_docstring(@lines) + statement + end + + def transform_ResourceTypeDefinition(o) + statement = PuppetStrings::Yard::Parsers::Puppet::DefinedTypeStatement.new(o, @file) + statement.extract_docstring(@lines) + statement + end + + def transform_FunctionDefinition(o) + statement = PuppetStrings::Yard::Parsers::Puppet::FunctionStatement.new(o, @file) + statement.extract_docstring(@lines) + statement + end + + def transform_Object(o) + # Ignore anything else (will be compacted out of the resulting array) + end +end diff --git a/lib/puppet-strings/yard/parsers/puppet/statement.rb b/lib/puppet-strings/yard/parsers/puppet/statement.rb new file mode 100644 index 0000000..8dd9868 --- /dev/null +++ b/lib/puppet-strings/yard/parsers/puppet/statement.rb @@ -0,0 +1,146 @@ +require 'puppet' +require 'puppet/pops' + +module PuppetStrings::Yard::Parsers::Puppet + # Represents the base Puppet language statement. + class Statement + # The pattern for parsing docstring comments. + COMMENT_REGEX = /^\s*#+\s?/ + + attr_reader :source + attr_reader :file + attr_reader :line + attr_reader :docstring + attr_reader :comments_range + + # Initializes the Puppet language statement. + # @param object The Puppet parser model object for the statement. + # @param [String] file The file name of the file containing the statement. + def initialize(object, file) + @file = file + + adapter = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(object) + @source = adapter.extract_text + @line = adapter.line + @comments_range = nil + end + + # Extracts the docstring for the statement given the source lines. + # @param [Array] lines The source lines for the file containing the statement. + # @return [void] + def extract_docstring(lines) + comment = [] + (0..@line-2).reverse_each do |index| + break unless index <= lines.count + line = lines[index].strip + count = line.size + line.gsub!(COMMENT_REGEX, '') + # Break out if nothing was removed (wasn't a comment line) + break unless line.size < count + comment << line + end + @comments_range = (@line - comment.size - 1..@line - 1) + @docstring = YARD::Docstring.new(comment.reverse.join("\n")) + end + + # Shows the first line context for the statement. + # @return [String] Returns the first line context for the statement. + def show + "\t#{@line}: #{first_line}" + end + + # Gets the full comments of the statement. + # @return [String] Returns the full comments of the statement. + def comments + @docstring.all + end + + # Determines if the comments have hash flag. + # @return [Boolean] Returns true if the comments have a hash flag or false if not. + def comments_hash_flag + false + end + + private + def first_line + @source.split(/\r?\n/).first.strip + end + end + + # Implements a parameterized statement (a statement that takes parameters). + class ParameterizedStatement < Statement + # Implements a parameter for a parameterized statement. + class Parameter + attr_reader :name + attr_reader :type + attr_reader :value + + # Initializes the parameter. + # @param [Puppet::Pops::Model::Parameter] parameter The parameter model object. + def initialize(parameter) + @name = parameter.name + # Take the exact text for the type expression + if parameter.type_expr + adapter = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(parameter.type_expr) + @type = adapter.extract_text + end + # Take the exact text for the default value expression + if parameter.value + adapter = ::Puppet::Pops::Adapters::SourcePosAdapter.adapt(parameter.value) + @value = adapter.extract_text + end + end + end + + attr_reader :parameters + + # Initializes the parameterized statement. + # @param object The Puppet parser model object that has parameters. + # @param [String] file The file containing the statement. + def initialize(object, file) + super(object, file) + @parameters = object.parameters.map { |parameter| Parameter.new(parameter) } + end + end + + # Implements the Puppet class statement. + class ClassStatement < ParameterizedStatement + attr_reader :name + attr_reader :parent_class + + # Initializes the Puppet class statement. + # @param [Puppet::Pops::Model::HostClassDefinition] object The model object for the class statement. + # @param [String] file The file containing the statement. + def initialize(object, file) + super(object, file) + @name = object.name + @parent_class = object.parent_class + end + end + + # Implements the Puppet defined type statement. + class DefinedTypeStatement < ParameterizedStatement + attr_reader :name + + # Initializes the Puppet defined type statement. + # @param [Puppet::Pops::Model::ResourceTypeDefinition] object The model object for the defined type statement. + # @param [String] file The file containing the statement. + def initialize(object, file) + super(object, file) + @name = object.name + end + end + + # Implements the Puppet function statement. + class FunctionStatement < ParameterizedStatement + attr_reader :name + + # Initializes the Puppet function statement. + # @param [Puppet::Pops::Model::FunctionDefinition] object The model object for the function statement. + # @param [String] file The file containing the statement. + def initialize(object, file) + super(object, file) + @name = object.name + end + end +end From 7c3cd5463c73e36486d5ba7ada67d40c76545456 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:20:28 -0700 Subject: [PATCH 06/15] (PDOC-63) Implement a Puppet class YARD handler. This commit implements a YARD handler for Puppet classes and the associated code object and templates. --- lib/puppet-strings/yard.rb | 10 +- lib/puppet-strings/yard/code_objects.rb | 1 + lib/puppet-strings/yard/code_objects/base.rb | 14 +++ lib/puppet-strings/yard/code_objects/class.rb | 44 ++++++++ lib/puppet-strings/yard/code_objects/group.rb | 30 +++++ lib/puppet-strings/yard/handlers.rb | 4 + .../yard/handlers/puppet/base.rb | 46 ++++++++ .../yard/handlers/puppet/class_handler.rb | 23 ++++ .../fulldoc/html/full_list_puppet_class.erb | 9 ++ .../templates/default/fulldoc/html/setup.rb | 28 +++++ .../templates/default/layout/html/objects.erb | 31 ++++++ .../templates/default/layout/html/setup.rb | 104 ++++++++++++++++++ .../default/puppet_class/html/box_info.erb | 26 +++++ .../default/puppet_class/html/header.erb | 1 + .../default/puppet_class/html/overview.erb | 6 + .../default/puppet_class/html/setup.rb | 14 +++ .../default/puppet_class/html/source.erb | 12 ++ .../yard/templates/default/tags/setup.rb | 8 ++ 18 files changed, 410 insertions(+), 1 deletion(-) create mode 100644 lib/puppet-strings/yard/code_objects/base.rb create mode 100644 lib/puppet-strings/yard/code_objects/class.rb create mode 100644 lib/puppet-strings/yard/code_objects/group.rb create mode 100644 lib/puppet-strings/yard/handlers/puppet/base.rb create mode 100644 lib/puppet-strings/yard/handlers/puppet/class_handler.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/layout/html/objects.erb create mode 100644 lib/puppet-strings/yard/templates/default/layout/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_class/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_class/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_class/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_class/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_class/html/source.erb create mode 100644 lib/puppet-strings/yard/templates/default/tags/setup.rb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 90d0be0..2a03364 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -15,6 +15,9 @@ module PuppetStrings::Yard # Register the Puppet parser YARD::Parser::SourceParser.register_parser_type(:puppet, PuppetStrings::Yard::Parsers::Puppet::Parser, ['pp']) + + # Register our handlers + YARD::Handlers::Processor.register_handler_namespace(:puppet, PuppetStrings::Yard::Handlers::Puppet) end end @@ -25,7 +28,8 @@ class YARD::CLI::Yardoc YARD::Registry.all( :root, :module, - :class + :class, + :puppet_class, ) end end @@ -34,6 +38,10 @@ end # This is the recommended way to add custom stats. # @private class YARD::CLI::Stats + def stats_for_puppet_classes + output 'Puppet Classes', *type_statistics_all(:puppet_class) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index d346ef7..93a5a0f 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -1,3 +1,4 @@ # The module for custom YARD code objects. module PuppetStrings::Yard::CodeObjects + require 'puppet-strings/yard/code_objects/class' end diff --git a/lib/puppet-strings/yard/code_objects/base.rb b/lib/puppet-strings/yard/code_objects/base.rb new file mode 100644 index 0000000..ba9840e --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/base.rb @@ -0,0 +1,14 @@ +# Implements the base code object. +class PuppetStrings::Yard::CodeObjects::Base < YARD::CodeObjects::NamespaceObject + # Allocates a new code object. + # @param [Array] args The arguments to initialize the code object with. + # @return Returns the code object. + def self.new(*args) + # Skip the super class' implementation because it detects :: in names and this will cause namespaces in the output we don't want + object = Object.class.instance_method(:new).bind(self).call(*args) + existing = YARD::Registry.at(object.path) + object = existing if existing && existing.class == self + yield(object) if block_given? + object + end +end diff --git a/lib/puppet-strings/yard/code_objects/class.rb b/lib/puppet-strings/yard/code_objects/class.rb new file mode 100644 index 0000000..71461c5 --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/class.rb @@ -0,0 +1,44 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet classes. +class PuppetStrings::Yard::CodeObjects::Classes < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @return Returns the singleton instance of the group. + def self.instance + super(:puppet_classes) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Puppet Classes' + end +end + +# Implements the Puppet class code object. +class PuppetStrings::Yard::CodeObjects::Class < PuppetStrings::Yard::CodeObjects::Base + attr_reader :statement + attr_reader :parameters + + # Initializes a Puppet class code object. + # @param [PuppetStrings::Parsers::ClassStatement] statement The class statement that was parsed. + # @return [void] + def initialize(statement) + @statement = statement + @parameters = statement.parameters.map { |p| [p.name, p.value] } + super(PuppetStrings::Yard::CodeObjects::Classes.instance, statement.name) + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_class + end + + # Gets the source of the code object. + # @return Returns the source of the code object. + def source + @statement.source + end +end diff --git a/lib/puppet-strings/yard/code_objects/group.rb b/lib/puppet-strings/yard/code_objects/group.rb new file mode 100644 index 0000000..f3becac --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/group.rb @@ -0,0 +1,30 @@ +require 'puppet-strings/yard/code_objects/base' + +# Implements the base class for "groups". +# +# A group behaves like a YARD namespace object, but displays differently in the HTML output. +class PuppetStrings::Yard::CodeObjects::Group < PuppetStrings::Yard::CodeObjects::Base + # Gets the singleton instance of the group. + # @param [Symbol] key The key to lookup the group for. + # @return Returns the singleton instance of the group. + def self.instance(key) + instance = P(:root, key) + return instance unless instance.is_a?(YARD::CodeObjects::Proxy) + instance = self.new(:root, key) + instance.visibility = :hidden + P(:root).children << instance + instance + end + + # Gets the path to the group. + # @return [String] Returns the path to the group. + def path + @name.to_s + end + + # Gets the type of the group. + # @return [Symbol] Returns the type of the group. + def type + @name + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index e502343..df90be1 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -1,3 +1,7 @@ # The module for custom YARD handlers. module PuppetStrings::Yard::Handlers + # The module for custom Puppet YARD handlers. + module Puppet + require 'puppet-strings/yard/handlers/puppet/class_handler' + end end diff --git a/lib/puppet-strings/yard/handlers/puppet/base.rb b/lib/puppet-strings/yard/handlers/puppet/base.rb new file mode 100644 index 0000000..0315b3c --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/base.rb @@ -0,0 +1,46 @@ +# Implements the base handler for Puppet language handlers. +class PuppetStrings::Yard::Handlers::Puppet::Base < YARD::Handlers::Base + # Determine sif the handler handles the given statement. + # @param statement The statement that was parsed. + # @return [Boolean] Returns true if the statement is handled by this handler or false if not. + def self.handles?(statement) + handlers.any? {|handler| statement.is_a?(handler)} + end + + protected + # Sets the parameter tag types for the given code object. + # This also performs some validation on the parameter tags. + # @param object The code object to set the parameter tag types for. + # @return [void] + def set_parameter_types(object) + # Ensure there is an actual parameter for each parameter tag + tags = object.tags(:param) + tags.each do |tag| + next if statement.parameters.find { |p| tag.name == p.name } + log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{statement.file}:#{statement.line}." + end + + # Assign the types for the parameter + statement.parameters.each do |parameter| + tag = tags.find { |t| t.name == parameter.name } + + unless tag + log.warn "Missing @param tag for parameter '#{parameter.name}' near #{statement.file}:#{statement.line}." unless object.docstring.empty? + + # Add a tag with an empty docstring + object.add_tag YARD::Tags::Tag.new(:param, '', [parameter.type || 'Any'], parameter.name) + object.parameters << [parameter.name, parameter.value] + next + end + + # Warn if the parameter is typed and the tag also has a type + log.warn "The @param tag for parameter '#{parameter.name}' should not contain a type specification near #{statement.file}:#{statement.line}: ignoring in favor of parameter type information." if parameter.type && tag.types && !tag.types.empty? + + if parameter.type + tag.types = [parameter.type] + elsif !tag.types + tag.types = ['Any'] + end + end + end +end diff --git a/lib/puppet-strings/yard/handlers/puppet/class_handler.rb b/lib/puppet-strings/yard/handlers/puppet/class_handler.rb new file mode 100644 index 0000000..9415bc5 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/class_handler.rb @@ -0,0 +1,23 @@ +require 'puppet-strings/yard/handlers/puppet/base' +require 'puppet-strings/yard/parsers' +require 'puppet-strings/yard/code_objects' + +# Implements the handler for Puppet classes. +class PuppetStrings::Yard::Handlers::Puppet::ClassHandler < PuppetStrings::Yard::Handlers::Puppet::Base + handles PuppetStrings::Yard::Parsers::Puppet::ClassStatement + + process do + # Register the object + object = PuppetStrings::Yard::CodeObjects::Class.new(statement) + register object + + # Log a warning if missing documentation + log.warn "Missing documentation for Puppet class '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + + # Set the parameter types + set_parameter_types(object) + + # Mark the class as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb new file mode 100644 index 0000000..095188f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_class.erb @@ -0,0 +1,9 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(true)) %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb new file mode 100644 index 0000000..0c58c0f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -0,0 +1,28 @@ +# Generates the searchable Puppet class list. +# @return [void] +def generate_puppet_class_list + @items = Registry.all(:puppet_class).sort_by { |c| c.name.to_s } + @list_title = 'Puppet Class List' + @list_type = 'puppet_class' + generate_list_contents +end + +# Generates the searchable Ruby method list. +# @return [void] +def generate_method_list + @items = prune_method_listing(Registry.all(:method), false) + @items = @items.reject {|m| m.name.to_s =~ /=$/ && m.is_attribute? } + @items = @items.sort_by {|m| m.name.to_s } + @list_title = 'Ruby Method List' + @list_type = 'method' + generate_list_contents +end + +# Generate a searchable Ruby class list in the output. +# @return [void] +def generate_class_list + @items = options.objects if options.objects + @list_title = 'Ruby Class List' + @list_type = 'class' + generate_list_contents +end diff --git a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb new file mode 100644 index 0000000..9395340 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb @@ -0,0 +1,31 @@ +<% unless @objects_by_letter.empty? %> +

    <%= @title %>

    + + <% i = 0 %> + + + + + +
    + <% @objects_by_letter.sort_by {|l,o| l.to_s }.each do |letter, objects| %> + <% if (i += 1) % 8 == 0 %> + + <% i = 0 %> + <% end %> +
      +
    • <%= letter %>
    • +
        + <% objects.each do |obj| %> +
      • + <%= linkify obj, obj.name %> + <% if (obj.type == :module || obj.type == :class) && !obj.namespace.root? %> + (<%= obj.namespace.path %>) + <% end %> +
      • + <% end %> +
      +
    + <% end %> +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb new file mode 100644 index 0000000..bd5a48e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -0,0 +1,104 @@ +# Initializes the template. +# @return [void] +def init + case object + when '_index.html' + @page_title = options.title + sections :layout, [:index, [:listing, [:classes, :files, :objects]]] + else + super + end +end + +# Renders the layout section. +# @return [String] Returns the rendered section. +def layout + @nav_url = url_for_list(!@file || options.index ? menu_lists.first[:type] : 'file') + + case object + when nil, String + @path = nil + when @file + @path = @file.path + when !object.is_a?(YARD::CodeObjects::NamespaceObject) + @path = object.parent.path + @nav_url = url_for_list('class') + when YARD::CodeObjects::ClassObject + @path = object.path + @nav_url = url_for_list('class') + when PuppetStrings::Yard::CodeObjects::Class + @nav_url = url_for_list('puppet_class') + @page_title = "Puppet Class: #{object.name}" + @path = object.path + else + @path = object.path + end + + erb(:layout) +end + +# Creates the dynamic menu lists. +# @return [Array] Returns the dynamic menu list. +def create_menu_lists + menu_lists = [ + { + type: 'puppet_class', + title: 'Puppet Classes', + search_title: 'Puppet Classes' + }, + { + type: 'class', + title: 'Ruby Classes', + search_title: 'Class List' + }, + { + type: 'method', + title: 'Ruby Methods', + search_title: 'Method List' + }, + ] + + menu_lists.delete_if { |e| YARD::Registry.all(e[:type].intern).empty? } + + # We must always return at least one group, so always keep the files list + menu_lists << { + type: 'file', + title: 'Files', + search_title: 'File List' + } if menu_lists.empty? || !YARD::Registry.all(:file).empty? + + menu_lists +end + +# Gets the menu lists to use. +# @return [Array + <% if object.statement.parent_class %> +
    +
    Inherits:
    +
    <%= linkify(Registry["puppet_classes::#{object.statement.parent_class}"], object.statement.parent_class.dup) %>
    +
    + <% end %> + <% if @subclasses && !@subclasses.empty? %> +
    +
    Inherited by:
    +
    + <% @subclasses.each do |subclass| %> + <%= linkify(subclass, subclass.name.to_s) %>
    + <% end %> +
    +
    + <% end %> +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %> + <% end %> +
    +
    + diff --git a/lib/puppet-strings/yard/templates/default/puppet_class/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_class/html/header.erb new file mode 100644 index 0000000..a7e847c --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_class/html/header.erb @@ -0,0 +1 @@ +

    Puppet Class: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_class/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_class/html/overview.erb new file mode 100644 index 0000000..a5b527a --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_class/html/overview.erb @@ -0,0 +1,6 @@ +

    Overview

    +
    +
    + <%= htmlify(object.docstring) %> +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_class/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_class/html/setup.rb new file mode 100644 index 0000000..2250d2f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_class/html/setup.rb @@ -0,0 +1,14 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, T('tags'), :source +end + +# Renders the box_info section. +# @return [String] Returns the rendered section. +def box_info + @subclasses = Registry.all(:puppet_class).find_all { |c| + c.statement.parent_class == object.name.to_s + } + erb(:box_info) +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_class/html/source.erb b/lib/puppet-strings/yard/templates/default/puppet_class/html/source.erb new file mode 100644 index 0000000..0fd3c5e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_class/html/source.erb @@ -0,0 +1,12 @@ +
    + + + + + +
    +
    <%= "\n\n\n" %><%= h format_lines(object) %>
    +
    +
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/tags/setup.rb b/lib/puppet-strings/yard/templates/default/tags/setup.rb new file mode 100644 index 0000000..be92cf0 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/tags/setup.rb @@ -0,0 +1,8 @@ +# Called to return parameter tags. +# @return [Array] Returns the parameter tags if the object should have parameters. +def param + tag(:param) if + object.type == :method || + object.type == :puppet_class +end + From 187dec9ceecd64113868f2459e15eb3879c7c9f5 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:27:26 -0700 Subject: [PATCH 07/15] (PDOC-63) Implement a Puppet defined type YARD handler. This commit implements a YARD handler for Puppet defined types and the associated code object and templates. --- lib/puppet-strings/yard.rb | 5 +++ lib/puppet-strings/yard/code_objects.rb | 1 + .../yard/code_objects/defined_type.rb | 44 +++++++++++++++++++ lib/puppet-strings/yard/handlers.rb | 1 + .../handlers/puppet/defined_type_handler.rb | 23 ++++++++++ .../html/full_list_puppet_defined_type.erb | 9 ++++ .../templates/default/fulldoc/html/setup.rb | 9 ++++ .../templates/default/layout/html/setup.rb | 19 +++++++- .../puppet_defined_type/html/box_info.erb | 10 +++++ .../puppet_defined_type/html/header.erb | 1 + .../puppet_defined_type/html/overview.erb | 6 +++ .../default/puppet_defined_type/html/setup.rb | 5 +++ .../puppet_defined_type/html/source.erb | 12 +++++ .../yard/templates/default/tags/setup.rb | 4 +- 14 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 lib/puppet-strings/yard/code_objects/defined_type.rb create mode 100644 lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_defined_type/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_defined_type/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_defined_type/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_defined_type/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_defined_type/html/source.erb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 2a03364..9fa71c0 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -30,6 +30,7 @@ class YARD::CLI::Yardoc :module, :class, :puppet_class, + :puppet_defined_type, ) end end @@ -42,6 +43,10 @@ class YARD::CLI::Stats output 'Puppet Classes', *type_statistics_all(:puppet_class) end + def stats_for_puppet_defined_types + output 'Puppet Defined Types', *type_statistics_all(:puppet_defined_type) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index 93a5a0f..da6af39 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -1,4 +1,5 @@ # The module for custom YARD code objects. module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/class' + require 'puppet-strings/yard/code_objects/defined_type' end diff --git a/lib/puppet-strings/yard/code_objects/defined_type.rb b/lib/puppet-strings/yard/code_objects/defined_type.rb new file mode 100644 index 0000000..12d4afb --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/defined_type.rb @@ -0,0 +1,44 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet defined types. +class PuppetStrings::Yard::CodeObjects::DefinedTypes < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @return Returns the singleton instance of the group. + def self.instance + super(:puppet_defined_types) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Defined Types' + end +end + +# Implements the Puppet defined type code object. +class PuppetStrings::Yard::CodeObjects::DefinedType < PuppetStrings::Yard::CodeObjects::Base + attr_reader :statement + attr_reader :parameters + + # Initializes a Puppet defined type code object. + # @param [PuppetStrings::Parsers::DefinedTypeStatement] statement The defined type statement that was parsed. + # @return [void] + def initialize(statement) + @statement = statement + @parameters = statement.parameters.map { |p| [p.name, p.value] } + super(PuppetStrings::Yard::CodeObjects::DefinedTypes.instance, statement.name) + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_defined_type + end + + # Gets the source of the code object. + # @return Returns the source of the code object. + def source + @statement.source + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index df90be1..9eadc55 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -3,5 +3,6 @@ module PuppetStrings::Yard::Handlers # The module for custom Puppet YARD handlers. module Puppet require 'puppet-strings/yard/handlers/puppet/class_handler' + require 'puppet-strings/yard/handlers/puppet/defined_type_handler' end end diff --git a/lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb b/lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb new file mode 100644 index 0000000..4786c24 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/defined_type_handler.rb @@ -0,0 +1,23 @@ +require 'puppet-strings/yard/handlers/puppet/base' +require 'puppet-strings/yard/parsers' +require 'puppet-strings/yard/code_objects' + +# Implements the handler for Puppet defined types. +class PuppetStrings::Yard::Handlers::Puppet::DefinedTypeHandler < PuppetStrings::Yard::Handlers::Puppet::Base + handles PuppetStrings::Yard::Parsers::Puppet::DefinedTypeStatement + + process do + # Register the object + object = PuppetStrings::Yard::CodeObjects::DefinedType.new(statement) + register object + + # Log a warning if missing documentation + log.warn "Missing documentation for Puppet defined type '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + + # Set the parameter types + set_parameter_types(object) + + # Mark the defined type as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb new file mode 100644 index 0000000..095188f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_defined_type.erb @@ -0,0 +1,9 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(true)) %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index 0c58c0f..70f4b3f 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -7,6 +7,15 @@ def generate_puppet_class_list generate_list_contents end +# Generates the searchable Puppet defined type list. +# @return [void] +def generate_puppet_defined_type_list + @items = Registry.all(:puppet_defined_type).sort_by {|dt| dt.name.to_s } + @list_title = 'Defined Type List' + @list_type = 'puppet_defined_type' + generate_list_contents +end + # Generates the searchable Ruby method list. # @return [void] def generate_method_list diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index bd5a48e..656e655 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :files, :objects]]] else super end @@ -30,6 +30,10 @@ def layout @nav_url = url_for_list('puppet_class') @page_title = "Puppet Class: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::DefinedType + @nav_url = url_for_list('puppet_defined_type') + @page_title = "Defined Type: #{object.name}" + @path = object.path else @path = object.path end @@ -46,6 +50,11 @@ def create_menu_lists title: 'Puppet Classes', search_title: 'Puppet Classes' }, + { + type: 'puppet_defined_type', + title: 'Defined Types', + search_title: 'Defined Types', + }, { type: 'class', title: 'Ruby Classes', @@ -95,6 +104,14 @@ def classes erb(:objects) end +# Renders the defined types section. +# @return [String] Returns the rendered section. +def defined_types + @title = 'Defined Type Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_defined_type) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/box_info.erb new file mode 100644 index 0000000..49a6460 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/box_info.erb @@ -0,0 +1,10 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + + diff --git a/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/header.erb new file mode 100644 index 0000000..91f06e7 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/header.erb @@ -0,0 +1 @@ +

    Defined Type: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/overview.erb new file mode 100644 index 0000000..a5b527a --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/overview.erb @@ -0,0 +1,6 @@ +

    Overview

    +
    +
    + <%= htmlify(object.docstring) %> +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/setup.rb new file mode 100644 index 0000000..d8858fb --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/setup.rb @@ -0,0 +1,5 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, T('tags'), :source +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/source.erb b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/source.erb new file mode 100644 index 0000000..0fd3c5e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_defined_type/html/source.erb @@ -0,0 +1,12 @@ +
    + + + + + +
    +
    <%= "\n\n\n" %><%= h format_lines(object) %>
    +
    +
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/tags/setup.rb b/lib/puppet-strings/yard/templates/default/tags/setup.rb index be92cf0..2166fdf 100644 --- a/lib/puppet-strings/yard/templates/default/tags/setup.rb +++ b/lib/puppet-strings/yard/templates/default/tags/setup.rb @@ -3,6 +3,6 @@ def param tag(:param) if object.type == :method || - object.type == :puppet_class + object.type == :puppet_class || + object.type == :puppet_defined_type end - From 22396a13d0f8983edb89187b7c9bd8e0296b4e16 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:39:08 -0700 Subject: [PATCH 08/15] (PDOC-63) Implement a Puppet resource type YARD handler. This commit implements a YARD handler for Puppet resource types and the associated code object and templates. --- lib/puppet-strings/yard.rb | 14 ++ lib/puppet-strings/yard/code_objects.rb | 1 + lib/puppet-strings/yard/code_objects/type.rb | 110 ++++++++++ lib/puppet-strings/yard/handlers.rb | 5 + lib/puppet-strings/yard/handlers/ruby/base.rb | 38 ++++ .../yard/handlers/ruby/type_handler.rb | 194 ++++++++++++++++++ lib/puppet-strings/yard/tags.rb | 2 + .../yard/tags/parameter_directive.rb | 24 +++ .../yard/tags/property_directive.rb | 24 +++ .../fulldoc/html/full_list_puppet_type.erb | 9 + .../templates/default/fulldoc/html/setup.rb | 9 + .../templates/default/layout/html/setup.rb | 19 +- .../default/puppet_type/html/box_info.erb | 20 ++ .../default/puppet_type/html/features.erb | 13 ++ .../default/puppet_type/html/header.erb | 1 + .../default/puppet_type/html/overview.erb | 6 + .../default/puppet_type/html/parameters.erb | 35 ++++ .../default/puppet_type/html/setup.rb | 32 +++ 18 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 lib/puppet-strings/yard/code_objects/type.rb create mode 100644 lib/puppet-strings/yard/handlers/ruby/base.rb create mode 100644 lib/puppet-strings/yard/handlers/ruby/type_handler.rb create mode 100644 lib/puppet-strings/yard/tags/parameter_directive.rb create mode 100644 lib/puppet-strings/yard/tags/property_directive.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/features.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/parameters.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 9fa71c0..8c92acd 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -18,6 +18,15 @@ module PuppetStrings::Yard # Register our handlers YARD::Handlers::Processor.register_handler_namespace(:puppet, PuppetStrings::Yard::Handlers::Puppet) + YARD::Handlers::Processor.register_handler_namespace(:puppet_ruby, PuppetStrings::Yard::Handlers::Ruby) + + # Register the tag directives + PuppetStrings::Yard::Tags::ParameterDirective.register! + PuppetStrings::Yard::Tags::PropertyDirective.register! + + # Ignore documentation on Puppet DSL calls + # This prevents the YARD DSL parser from emitting warnings for Puppet's Ruby DSL + YARD::Handlers::Ruby::DSLHandlerMethods::IGNORE_METHODS['newtype'] = true end end @@ -31,6 +40,7 @@ class YARD::CLI::Yardoc :class, :puppet_class, :puppet_defined_type, + :puppet_type, ) end end @@ -47,6 +57,10 @@ class YARD::CLI::Stats output 'Puppet Defined Types', *type_statistics_all(:puppet_defined_type) end + def stats_for_puppet_types + output 'Puppet Types', *type_statistics_all(:puppet_type) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index da6af39..dc6b9e3 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -2,4 +2,5 @@ module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/class' require 'puppet-strings/yard/code_objects/defined_type' + require 'puppet-strings/yard/code_objects/type' end diff --git a/lib/puppet-strings/yard/code_objects/type.rb b/lib/puppet-strings/yard/code_objects/type.rb new file mode 100644 index 0000000..bf80e14 --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/type.rb @@ -0,0 +1,110 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet resource types. +class PuppetStrings::Yard::CodeObjects::Types < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @return Returns the singleton instance of the group. + def self.instance + super(:puppet_types) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Resource Types' + end +end + +# Implements the Puppet resource type code object. +class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects::Base + # Represents a resource type parameter. + class Parameter + attr_reader :name, :values, :aliases + attr_accessor :docstring, :isnamevar, :default + + # Initializes a resource type parameter or property. + # @param [String] name The name of the parameter or property. + # @param [String] docstring The docstring for the parameter or property.s + def initialize(name, docstring = nil) + @name = name + @docstring = docstring || '' + @values = [] + @aliases = {} + @isnamevar = false + @default = nil + end + + # Adds a value to the parameter or property. + # @param [String] value The value to add. + # @return [void] + def add(value) + @values << value + end + + # Aliases a value to another value. + # @param [String] new The new (alias) value. + # @param [String] old The old (existing) value. + # @return [void] + def alias(new, old) + @values << new unless @values.include? new + @aliases[new] = old + end + end + + # Represents a resource type property (same attributes as a parameter). + class Property < Parameter + end + + # Represents a resource type feature. + class Feature + attr_reader :name, :docstring + + # Initializes a new feature. + # @param [String] name The name of the feature. + # @param [String] docstring The docstring of the feature. + def initialize(name, docstring) + @name = name + @docstring = docstring + end + end + + attr_reader :properties, :parameters, :features + + # Initializes a new resource type. + # @param [String] name The resource type name. + # @return [void] + def initialize(name) + super(PuppetStrings::Yard::CodeObjects::Types.instance, name) + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_type + end + + # Adds a parameter to the resource type + # @param [PuppetStrings::Yard::CodeObjects::Type::Parameter] parameter The parameter to add. + # @return [void] + def add_parameter(parameter) + @parameters ||= [] + @parameters << parameter + end + + # Adds a property to the resource type + # @param [PuppetStrings::Yard::CodeObjects::Type::Property] property The property to add. + # @return [void] + def add_property(property) + @properties ||= [] + @properties << property + end + + # Adds a feature to the resource type. + # @param [PuppetStrings::Yard::CodeObjects::Type::Feature] feature The feature to add. + # @return [void] + def add_feature(feature) + @features ||= [] + @features << feature + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index 9eadc55..f3c683c 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -1,5 +1,10 @@ # The module for custom YARD handlers. module PuppetStrings::Yard::Handlers + # The module for custom Ruby YARD handlers. + module Ruby + require 'puppet-strings/yard/handlers/ruby/type_handler' + end + # The module for custom Puppet YARD handlers. module Puppet require 'puppet-strings/yard/handlers/puppet/class_handler' diff --git a/lib/puppet-strings/yard/handlers/ruby/base.rb b/lib/puppet-strings/yard/handlers/ruby/base.rb new file mode 100644 index 0000000..d2fb041 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/ruby/base.rb @@ -0,0 +1,38 @@ +require 'ripper' + +# Implements the base handler for Ruby language handlers. +class PuppetStrings::Yard::Handlers::Ruby::Base < YARD::Handlers::Ruby::Base + # A regular expression for detecting the start of a Ruby heredoc. + # Note: the first character of the heredoc start may have been cut off by YARD. + HEREDOC_START = /^ 1 + end + + source + end + end +end diff --git a/lib/puppet-strings/yard/handlers/ruby/type_handler.rb b/lib/puppet-strings/yard/handlers/ruby/type_handler.rb new file mode 100644 index 0000000..86ee94e --- /dev/null +++ b/lib/puppet-strings/yard/handlers/ruby/type_handler.rb @@ -0,0 +1,194 @@ +require 'puppet-strings/yard/handlers/ruby/base' +require 'puppet-strings/yard/code_objects' +require 'puppet/util' + +# Implements the handler for Puppet resource types written in Ruby. +class PuppetStrings::Yard::Handlers::Ruby::TypeHandler < PuppetStrings::Yard::Handlers::Ruby::Base + # The default docstring when ensurable is used without given a docstring. + DEFAULT_ENSURABLE_DOCSTRING = 'The basic property that the resource should be in.'.freeze + + namespace_only + handles method_call(:newtype) + + process do + # Only accept calls to Puppet::Type + return unless statement.count > 1 + module_name = statement[0].source + return unless module_name == 'Puppet::Type' || module_name == 'Type' + + object = PuppetStrings::Yard::CodeObjects::Type.new(get_name) + register object + + docstring = find_docstring(statement, "Puppet resource type '#{object.name}'") + register_docstring(object, docstring, nil) if docstring + + # Populate the parameters/properties/features to the type + populate_type_data(object) + + # Set the default namevar + set_default_namevar(object) + + # Mark the type as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def get_name + parameters = statement.parameters(false) + raise YARD::Parser::UndocumentableError, "Expected at least one parameter to Puppet::Type.newtype at #{statement.file}:#{statement.line}." if parameters.empty? + name = node_as_string(parameters.first) + raise YARD::Parser::UndocumentableError, "Expected a symbol or string literal for first parameter but found '#{parameters.first.type}' at #{statement.file}:#{statement.line}." unless name + name + end + + def find_docstring(node, kind) + # Walk the tree searching for assignments or calls to desc/doc= + node.traverse do |child| + if child.type == :assign + ivar = child.jump(:ivar) + next unless ivar != child && ivar.source == '@doc' + docstring = node_as_string(child[1]) + log.error "Failed to parse docstring for #{kind} near #{child.file}:#{child.line}." and return nil unless docstring + return Puppet::Util::Docs.scrub(docstring) + elsif child.is_a?(YARD::Parser::Ruby::MethodCallNode) + # Look for a call to a dispatch method with a block + next unless child.method_name && + (child.method_name.source == 'desc' || child.method_name.source == 'doc=') && + child.parameters(false).count == 1 + + docstring = node_as_string(child.parameters[0]) + log.error "Failed to parse docstring for #{kind} near #{child.file}:#{child.line}." and return nil unless docstring + return Puppet::Util::Docs.scrub(docstring) + end + end + log.warn "Missing a description for #{kind} at #{node.file}:#{node.line}." + nil + end + + def populate_type_data(object) + # Traverse the block looking for properties/parameters/features + block = statement.block + return unless block && block.count >= 2 + block[1].children.each do |node| + next unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && + node.method_name + + method_name = node.method_name.source + parameters = node.parameters(false) + + if method_name == 'newproperty' + # Add a property to the object + next unless parameters.count >= 1 + name = node_as_string(parameters[0]) + next unless name + object.add_property(create_property(name, node)) + elsif method_name == 'newparam' + # Add a parameter to the object + next unless parameters.count >= 1 + name = node_as_string(parameters[0]) + next unless name + object.add_parameter(create_parameter(name, node)) + elsif method_name == 'feature' + # Add a feature to the object + next unless parameters.count >= 2 + name = node_as_string(parameters[0]) + next unless name + + docstring = node_as_string(parameters[1]) + next unless docstring + + object.add_feature(PuppetStrings::Yard::CodeObjects::Type::Feature.new(name, docstring)) + elsif method_name == 'ensurable' + if node.block + property = create_property('ensure', node) + property.docstring = DEFAULT_ENSURABLE_DOCSTRING if property.docstring.empty? + else + property = PuppetStrings::Yard::CodeObjects::Type::Property.new('ensure', DEFAULT_ENSURABLE_DOCSTRING) + property.add('present') + property.add('absent') + property.default = 'present' + end + object.add_property property + end + end + end + + def create_parameter(name, node) + parameter = PuppetStrings::Yard::CodeObjects::Type::Parameter.new(name, find_docstring(node, "Puppet resource parameter '#{name}'")) + set_values(node, parameter) + parameter + end + + def create_property(name, node) + property = PuppetStrings::Yard::CodeObjects::Type::Property.new(name, find_docstring(node, "Puppet resource property '#{name}'")) + set_values(node, property) + property + end + + def set_values(node, object) + return unless node.block && node.block.count >= 2 + + node.block[1].children.each do |child| + next unless child.is_a?(YARD::Parser::Ruby::MethodCallNode) && child.method_name + + method_name = child.method_name.source + parameters = child.parameters(false) + + if method_name == 'newvalue' + next unless parameters.count >= 1 + object.add(node_as_string(parameters[0]) || parameters[0].source) + elsif method_name == 'newvalues' + parameters.each do |p| + object.add(node_as_string(p) || p.source) + end + elsif method_name == 'aliasvalue' + next unless parameters.count >= 2 + object.alias(node_as_string(parameters[0]) || parameters[0].source, node_as_string(parameters[1]) || parameters[1].source) + elsif method_name == 'defaultto' + next unless parameters.count >= 1 + object.default = node_as_string(parameters[0]) || parameters[0].source + elsif method_name == 'isnamevar' + object.isnamevar = true + elsif method_name == 'defaultvalues' && object.name == 'ensure' + object.add('present') + object.add('absent') + object.default = 'present' + end + end + if object.is_a? PuppetStrings::Yard::CodeObjects::Type::Parameter + # Process the options for parameter base types + parameters = node.parameters(false) + if parameters.count >= 2 + parameters[1].each do |kvp| + next unless kvp.count == 2 + next unless node_as_string(kvp[0]) == 'parent' + if kvp[1].source == 'Puppet::Parameter::Boolean' + object.add('true') unless object.values.include? 'true' + object.add('false') unless object.values.include? 'false' + object.add('yes') unless object.values.include? 'yes' + object.add('no') unless object.values.include? 'no' + end + break + end + end + end + end + + def set_default_namevar(object) + return unless object.properties || object.parameters + default = nil + if object.properties + object.properties.each do |property| + return nil if property.isnamevar + default = property if property.name == 'name' + end + end + if object.parameters + object.parameters.each do |parameter| + return nil if parameter.isnamevar + default ||= parameter if parameter.name == 'name' + end + end + default.isnamevar = true if default + end +end diff --git a/lib/puppet-strings/yard/tags.rb b/lib/puppet-strings/yard/tags.rb index 8bd1d4b..ed0ffa9 100644 --- a/lib/puppet-strings/yard/tags.rb +++ b/lib/puppet-strings/yard/tags.rb @@ -1,3 +1,5 @@ # The module for custom YARD tags. module PuppetStrings::Yard::Tags + require 'puppet-strings/yard/tags/parameter_directive' + require 'puppet-strings/yard/tags/property_directive' end diff --git a/lib/puppet-strings/yard/tags/parameter_directive.rb b/lib/puppet-strings/yard/tags/parameter_directive.rb new file mode 100644 index 0000000..9cf68f9 --- /dev/null +++ b/lib/puppet-strings/yard/tags/parameter_directive.rb @@ -0,0 +1,24 @@ +require 'puppet-strings/yard/code_objects' + +# Implements a parameter directive (e.g. #@!puppet.type.param) for documenting Puppet resource types. +class PuppetStrings::Yard::Tags::ParameterDirective < YARD::Tags::Directive + # Called to invoke the directive. + # @return [void] + def call + return unless object && object.respond_to?(:add_parameter) + # Add a parameter to the resource + parameter = PuppetStrings::Yard::CodeObjects::Type::Parameter.new(tag.name, tag.text) + if tag.types + tag.types.each do |value| + parameter.add(value) + end + end + object.add_parameter parameter + end + + # Registers the directive with YARD. + # @return [void] + def self.register! + YARD::Tags::Library.define_directive('puppet.type.param', :with_types_and_name, self) + end +end diff --git a/lib/puppet-strings/yard/tags/property_directive.rb b/lib/puppet-strings/yard/tags/property_directive.rb new file mode 100644 index 0000000..a1c1e00 --- /dev/null +++ b/lib/puppet-strings/yard/tags/property_directive.rb @@ -0,0 +1,24 @@ +require 'puppet-strings/yard/code_objects' + +# Implements a parameter directive (e.g. #@!puppet.type.property) for documenting Puppet resource types. +class PuppetStrings::Yard::Tags::PropertyDirective < YARD::Tags::Directive + # Called to invoke the directive. + # @return [void] + def call + return unless object && object.respond_to?(:add_property) + # Add a property to the resource + property = PuppetStrings::Yard::CodeObjects::Type::Property.new(tag.name, tag.text) + if tag.types + tag.types.each do |value| + property.add(value) + end + end + object.add_property property + end + + # Registers the directive with YARD. + # @return [void] + def self.register! + YARD::Tags::Library.define_directive('puppet.type.property', :with_types_and_name, self) + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb new file mode 100644 index 0000000..095188f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_type.erb @@ -0,0 +1,9 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(true)) %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index 70f4b3f..86b3e10 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -16,6 +16,15 @@ def generate_puppet_defined_type_list generate_list_contents end +# Generates the searchable Puppet resource type list. +# @return [void] +def generate_puppet_type_list + @items = Registry.all(:puppet_type).sort_by {|t| t.name.to_s } + @list_title = 'Resource Type List' + @list_type = 'puppet_type' + generate_list_contents +end + # Generates the searchable Ruby method list. # @return [void] def generate_method_list diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index 656e655..11ea423 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :defined_types, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :files, :objects]]] else super end @@ -34,6 +34,10 @@ def layout @nav_url = url_for_list('puppet_defined_type') @page_title = "Defined Type: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::Type + @nav_url = url_for_list('puppet_type') + @page_title = "Resource Type: #{object.name}" + @path = object.path else @path = object.path end @@ -55,6 +59,11 @@ def create_menu_lists title: 'Defined Types', search_title: 'Defined Types', }, + { + type: 'puppet_type', + title: 'Resource Types', + search_title: 'Resource Types' + }, { type: 'class', title: 'Ruby Classes', @@ -112,6 +121,14 @@ def defined_types erb(:objects) end +# Renders the types section. +# @return [String] Returns the rendered section. +def types + @title = 'Resource Type Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_type) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_type/html/box_info.erb new file mode 100644 index 0000000..0276e3f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/box_info.erb @@ -0,0 +1,20 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + + <% if @providers && !@providers.empty? %> +
    +
    Providers:
    +
    + <% @providers.each do |provider| %> + <%= linkify(provider, provider.name.to_s) %>
    + <% end %> +
    +
    + <% end %> + diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/features.erb b/lib/puppet-strings/yard/templates/default/puppet_type/html/features.erb new file mode 100644 index 0000000..1cba5c5 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/features.erb @@ -0,0 +1,13 @@ +<% if object.features && !object.features.empty? %> +
    +

    Features

    +
      + <% object.features.each do |feature| %> +
    • + <%= feature.name %> + <% unless feature.docstring.empty? %> — <%= htmlify_line(feature.docstring) %><% end %> +
    • + <% end %> +
    +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_type/html/header.erb new file mode 100644 index 0000000..3f79aeb --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/header.erb @@ -0,0 +1 @@ +

    Resource Type: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_type/html/overview.erb new file mode 100644 index 0000000..a5b527a --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/overview.erb @@ -0,0 +1,6 @@ +

    Overview

    +
    +
    + <%= htmlify(object.docstring) %> +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/parameters.erb b/lib/puppet-strings/yard/templates/default/puppet_type/html/parameters.erb new file mode 100644 index 0000000..2e75754 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/parameters.erb @@ -0,0 +1,35 @@ +<% if @parameters && !@parameters.empty? %> +
    +

    <%= @tag_title %>

    +
      + <% @parameters.each do |parameter| %> +
    • + <%= parameter.name + (parameter.isnamevar ? ' (namevar)' : '') %> + <% if parameter.default %> + (defaults to: <%= parameter.default %>) + <% end %> + <% unless parameter.docstring.empty? %> +
      +
      + <%= htmlify(parameter.docstring) %> +
      +
      + <% end %> + <% unless parameter.values.empty? %> +
      + Supported values: +
        + <% parameter.values.each do |value| %> +
      • + <% other = parameter.aliases[value] %> + <%= value %><% if other %> (alias for: <%= other %>)<% end %> +
      • + <% end %> +
      +
      + <% end %> +
    • + <% end %> +
    +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb new file mode 100644 index 0000000..35c0b24 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb @@ -0,0 +1,32 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, T('tags'), :properties, :parameters, :features +end + +# Renders the box_info section. +# @return [String] Returns the rendered section. +def box_info + @providers = [] + erb(:box_info) +end + +# Renders the properties section. +# @return [String] Returns the rendered section. +def properties + # Properties are the same thing as parameters (from the documentation standpoint), + # so reuse the same template but with a different title and data source. + @parameters = object.properties || [] + @parameters.sort_by! { |p| p.name } + @tag_title = 'Properties' + erb(:parameters) +end + +# Renders the parameters section. +# @return [String] Returns the rendered section. +def parameters + @parameters = object.parameters || [] + @parameters.sort_by! { |p| p.name } + @tag_title = 'Parameters' + erb(:parameters) +end From b1a15bd43aa04dbd0c4da715065f1c98d89f3535 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:47:33 -0700 Subject: [PATCH 09/15] (PDOC-63) Implement a Puppet provider YARD handler. This commit implements a YARD handler for Puppet providers and the associated code object and templates. --- lib/puppet-strings/yard.rb | 5 + lib/puppet-strings/yard/code_objects.rb | 1 + .../yard/code_objects/provider.rb | 77 ++++++++++++ lib/puppet-strings/yard/handlers.rb | 1 + .../yard/handlers/ruby/provider_handler.rb | 112 ++++++++++++++++++ .../html/full_list_puppet_provider.erb | 10 ++ .../templates/default/fulldoc/html/setup.rb | 9 ++ .../templates/default/layout/html/objects.erb | 2 + .../templates/default/layout/html/setup.rb | 19 ++- .../default/puppet_provider/html/box_info.erb | 14 +++ .../puppet_provider/html/collection.erb | 10 ++ .../default/puppet_provider/html/features.erb | 12 ++ .../default/puppet_provider/html/header.erb | 1 + .../default/puppet_provider/html/overview.erb | 6 + .../default/puppet_provider/html/setup.rb | 29 +++++ .../default/puppet_type/html/setup.rb | 2 +- 16 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 lib/puppet-strings/yard/code_objects/provider.rb create mode 100644 lib/puppet-strings/yard/handlers/ruby/provider_handler.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/collection.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/features.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_provider/html/setup.rb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 8c92acd..ce3106b 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -41,6 +41,7 @@ class YARD::CLI::Yardoc :puppet_class, :puppet_defined_type, :puppet_type, + :puppet_provider, ) end end @@ -61,6 +62,10 @@ class YARD::CLI::Stats output 'Puppet Types', *type_statistics_all(:puppet_type) end + def stats_for_puppet_providers + output 'Puppet Providers', *type_statistics_all(:puppet_provider) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index dc6b9e3..d2c60db 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -3,4 +3,5 @@ module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/class' require 'puppet-strings/yard/code_objects/defined_type' require 'puppet-strings/yard/code_objects/type' + require 'puppet-strings/yard/code_objects/provider' end diff --git a/lib/puppet-strings/yard/code_objects/provider.rb b/lib/puppet-strings/yard/code_objects/provider.rb new file mode 100644 index 0000000..8a30075 --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/provider.rb @@ -0,0 +1,77 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet providers. +class PuppetStrings::Yard::CodeObjects::Providers < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @param [String] type The resource type name for the provider. + # @return Returns the singleton instance of the group. + def self.instance(type) + super("puppet_providers_#{type}".intern) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Providers' + end +end + +# Implements the Puppet provider code object. +class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObjects::Base + attr_reader :type_name, :confines, :features, :defaults, :commands + + # Initializes a Puppet provider code object. + # @param [String] type_name The resource type name for the provider. + # @param [String] name The name of the provider.s + # @return [void] + def initialize(type_name, name) + @type_name = type_name + super(PuppetStrings::Yard::CodeObjects::Providers.instance(type_name), name) + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_provider + end + + # Adds a confine to the provider. + # @param [String] key The confine's key. + # @param [String] value The confine's value. + # @return [void] + def add_confine(key, value) + return unless key && value + @confines ||= {} + @confines[key] = value + end + + # Adds a feature to the provider. + # @param [String] feature The feature to add to the provider. + # @return [void] + def add_feature(feature) + return unless feature + @features ||= [] + @features << feature + end + + # Adds a default to the provider. + # @param [String] key The default's key. + # @param [String] value The default's value. + # @return [void] + def add_default(key, value) + return unless key && value + @defaults ||= {} + @defaults[key] = value + end + + # Adds a command to the provider. + # @param [String] key The command's key. + # @param [String] value The command's value. + # @return [void] + def add_command(key, value) + return unless key && value + @commands ||= {} + @commands[key] = value + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index f3c683c..655e309 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -3,6 +3,7 @@ module PuppetStrings::Yard::Handlers # The module for custom Ruby YARD handlers. module Ruby require 'puppet-strings/yard/handlers/ruby/type_handler' + require 'puppet-strings/yard/handlers/ruby/provider_handler' end # The module for custom Puppet YARD handlers. diff --git a/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb b/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb new file mode 100644 index 0000000..89929c9 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb @@ -0,0 +1,112 @@ +require 'puppet-strings/yard/handlers/ruby/base' +require 'puppet-strings/yard/code_objects' +require 'puppet/util/docs' + +# Implements the handler for Puppet providers written in Ruby. +class PuppetStrings::Yard::Handlers::Ruby::ProviderHandler < PuppetStrings::Yard::Handlers::Ruby::Base + namespace_only + handles method_call(:provide) + + process do + return unless statement.count >= 2 + + # Check that provide is being called on Puppet::Type.type() + type_call = statement[0] + return unless type_call.is_a?(YARD::Parser::Ruby::MethodCallNode) && type_call.count >= 3 + return unless type_call[0].source == 'Puppet::Type' + return unless type_call[2].source == 'type' + + # Extract the type name + type_call_parameters = type_call.parameters(false) + return unless type_call_parameters.count >= 1 + type_name = node_as_string(type_call_parameters.first) + raise YARD::Parser::UndocumentableError, "Could not determine the resource type name for the provider defined at #{statement.file}:#{statement.line}." unless type_name + + # Register the object + object = PuppetStrings::Yard::CodeObjects::Provider.new(type_name, get_name) + register object + + # Extract the docstring + register_provider_docstring object + + # Populate the provider data + populate_provider_data object + + # Mark the provider as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def get_name + parameters = statement.parameters(false) + raise YARD::Parser::UndocumentableError, "Expected at least one parameter to 'provide' at #{statement.file}:#{statement.line}." if parameters.empty? + name = node_as_string(parameters.first) + raise YARD::Parser::UndocumentableError, "Expected a symbol or string literal for first parameter but found '#{parameters.first.type}' at #{statement.file}:#{statement.line}." unless name + name + end + + def register_provider_docstring(object) + # Walk the tree searching for assignments or calls to desc/doc= + statement.traverse do |child| + if child.type == :assign + ivar = child.jump(:ivar) + next unless ivar != child && ivar.source == '@doc' + docstring = node_as_string(child[1]) + log.error "Failed to parse docstring for Puppet provider '#{object.name}' (resource type '#{object.type_name}') near #{child.file}:#{child.line}." and return nil unless docstring + register_docstring(object, Puppet::Util::Docs.scrub(docstring), nil) + return nil + elsif child.is_a?(YARD::Parser::Ruby::MethodCallNode) + # Look for a call to a dispatch method with a block + next unless child.method_name && + (child.method_name.source == 'desc' || child.method_name.source == 'doc=') && + child.parameters(false).count == 1 + + docstring = node_as_string(child.parameters[0]) + log.error "Failed to parse docstring for Puppet provider '#{object.name}' (resource type '#{object.type_name}') near #{child.file}:#{child.line}." and return nil unless docstring + register_docstring(object, Puppet::Util::Docs.scrub(docstring), nil) + return nil + end + end + log.warn "Missing a description for Puppet provider '#{object.name}' (resource type '#{object.type_name}') at #{statement.file}:#{statement.line}." + end + + def populate_provider_data(object) + # Traverse the block looking for confines/defaults/commands + block = statement.block + return unless block && block.count >= 2 + block[1].children.each do |node| + next unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && node.method_name + + method_name = node.method_name.source + parameters = node.parameters(false) + + if method_name == 'confine' + # Add a confine to the object + next unless parameters.count >= 1 + parameters[0].each do |kvp| + next unless kvp.count == 2 + object.add_confine(node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source) + end + elsif method_name == 'has_feature' || method_name == 'has_features' + # Add the features to the object + parameters.each do |parameter| + object.add_feature(node_as_string(parameter) || parameter.source) + end + elsif method_name == 'defaultfor' + # Add a default to the object + next unless parameters.count >= 1 + parameters[0].each do |kvp| + next unless kvp.count == 2 + object.add_default(node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source) + end + elsif method_name == 'commands' + # Add the commands to the object + next unless parameters.count >= 1 + parameters[0].each do |kvp| + next unless kvp.count == 2 + object.add_command(node_as_string(kvp[0]) || kvp[0].source, node_as_string(kvp[1]) || kvp[1].source) + end + end + end + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb new file mode 100644 index 0000000..ec95e02 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_provider.erb @@ -0,0 +1,10 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(true)) %> + Resource type: <%=item.type_name%> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index 86b3e10..cdc18c5 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -25,6 +25,15 @@ def generate_puppet_type_list generate_list_contents end +# Generates the searchable Puppet provider list. +# @return [void] +def generate_puppet_provider_list + @items = Registry.all(:puppet_provider).sort_by {|p| p.name.to_s } + @list_title = 'Provider List' + @list_type = 'puppet_provider' + generate_list_contents +end + # Generates the searchable Ruby method list. # @return [void] def generate_method_list diff --git a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb index 9395340..ac5c815 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb +++ b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb @@ -19,6 +19,8 @@ <%= linkify obj, obj.name %> <% if (obj.type == :module || obj.type == :class) && !obj.namespace.root? %> (<%= obj.namespace.path %>) + <% elsif obj.type == :puppet_provider %> + (Resource type: <%= obj.type_name %>) <% end %> <% end %> diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index 11ea423..91a79ac 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :files, :objects]]] else super end @@ -38,6 +38,10 @@ def layout @nav_url = url_for_list('puppet_type') @page_title = "Resource Type: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::Provider + @nav_url = url_for_list('puppet_provider') + @page_title = "Provider: #{object.name}" + @path = object.path else @path = object.path end @@ -64,6 +68,11 @@ def create_menu_lists title: 'Resource Types', search_title: 'Resource Types' }, + { + type: 'puppet_provider', + title: 'Providers', + search_title: 'Providers' + }, { type: 'class', title: 'Ruby Classes', @@ -129,6 +138,14 @@ def types erb(:objects) end +# Renders the providers section. +# @return [String] Returns the rendered section. +def providers + @title = 'Puppet Provider Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_provider) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/box_info.erb new file mode 100644 index 0000000..6dc586f --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/box_info.erb @@ -0,0 +1,14 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + +
    +
    Resource type:
    +
    <%= linkify(Registry["puppet_types::#{object.type_name}"], object.type_name) %>
    +
    + diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/collection.erb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/collection.erb new file mode 100644 index 0000000..ec1bdf8 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/collection.erb @@ -0,0 +1,10 @@ +<% if @collection && !@collection.empty? %> +
    +

    <%= @title %>

    +
      + <% @collection.each do |key, value| %> +
    • <%= key %> — <%= value %>
    • + <% end %> +
    +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/features.erb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/features.erb new file mode 100644 index 0000000..fa3fa3e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/features.erb @@ -0,0 +1,12 @@ +<% if object.features && !object.features.empty? %> +
    +

    Features

    +
      + <% object.features.each do |feature| %> +
    • + <%= feature %> +
    • + <% end %> +
    +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/header.erb new file mode 100644 index 0000000..005785c --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/header.erb @@ -0,0 +1 @@ +

    Provider: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/overview.erb new file mode 100644 index 0000000..a5b527a --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/overview.erb @@ -0,0 +1,6 @@ +

    Overview

    +
    +
    + <%= htmlify(object.docstring) %> +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_provider/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_provider/html/setup.rb new file mode 100644 index 0000000..57a69a4 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_provider/html/setup.rb @@ -0,0 +1,29 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, T('tags'), :features, :confines, :defaults, :commands +end + +# Renders the confines section. +# @return [String] Returns the rendered section. +def confines + @title = 'Confines' + @collection = object.confines + erb(:collection) +end + +# Renders the defaults section. +# @return [String] Returns the rendered section. +def defaults + @title = 'Default Provider For' + @collection = object.defaults + erb(:collection) +end + +# Renders the commands section. +# @return [String] Returns the rendered section. +def commands + @title = 'Commands' + @collection = object.commands + erb(:collection) +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb index 35c0b24..d0a3043 100644 --- a/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/puppet_type/html/setup.rb @@ -7,7 +7,7 @@ end # Renders the box_info section. # @return [String] Returns the rendered section. def box_info - @providers = [] + @providers = PuppetStrings::Yard::CodeObjects::Providers.instance(object.name).children erb(:box_info) end From f025efe557746cee57343239d9be563ac4990982 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 11:54:55 -0700 Subject: [PATCH 10/15] (PDOC-63) Implement a Puppet function YARD handler. This commit implements a YARD handler for Puppet functions and the associated code object and templates. --- lib/puppet-strings/yard.rb | 6 + lib/puppet-strings/yard/code_objects.rb | 1 + .../yard/code_objects/function.rb | 75 ++++ lib/puppet-strings/yard/handlers.rb | 2 + .../yard/handlers/puppet/function_handler.rb | 42 +++ .../yard/handlers/ruby/function_handler.rb | 357 ++++++++++++++++++ lib/puppet-strings/yard/tags.rb | 1 + lib/puppet-strings/yard/tags/overload_tag.rb | 94 +++++ .../html/full_list_puppet_function.erb | 10 + .../templates/default/fulldoc/html/setup.rb | 9 + .../templates/default/layout/html/objects.erb | 2 + .../templates/default/layout/html/setup.rb | 19 +- .../default/puppet_function/html/box_info.erb | 14 + .../default/puppet_function/html/header.erb | 1 + .../default/puppet_function/html/overview.erb | 18 + .../default/puppet_function/html/setup.rb | 5 + .../default/puppet_function/html/source.erb | 12 + .../default/tags/html/puppet_overload.erb | 12 + .../yard/templates/default/tags/setup.rb | 9 +- 19 files changed, 687 insertions(+), 2 deletions(-) create mode 100644 lib/puppet-strings/yard/code_objects/function.rb create mode 100644 lib/puppet-strings/yard/handlers/puppet/function_handler.rb create mode 100644 lib/puppet-strings/yard/handlers/ruby/function_handler.rb create mode 100644 lib/puppet-strings/yard/tags/overload_tag.rb create mode 100644 lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb create mode 100644 lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb create mode 100644 lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index ce3106b..7e61cde 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -26,6 +26,7 @@ module PuppetStrings::Yard # Ignore documentation on Puppet DSL calls # This prevents the YARD DSL parser from emitting warnings for Puppet's Ruby DSL + YARD::Handlers::Ruby::DSLHandlerMethods::IGNORE_METHODS['create_function'] = true YARD::Handlers::Ruby::DSLHandlerMethods::IGNORE_METHODS['newtype'] = true end end @@ -42,6 +43,7 @@ class YARD::CLI::Yardoc :puppet_defined_type, :puppet_type, :puppet_provider, + :puppet_function, ) end end @@ -66,6 +68,10 @@ class YARD::CLI::Stats output 'Puppet Providers', *type_statistics_all(:puppet_provider) end + def stats_for_puppet_functions + output 'Puppet Functions', *type_statistics_all(:puppet_function) + end + def output(name, data, undoc = nil) # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc diff --git a/lib/puppet-strings/yard/code_objects.rb b/lib/puppet-strings/yard/code_objects.rb index d2c60db..076eb90 100644 --- a/lib/puppet-strings/yard/code_objects.rb +++ b/lib/puppet-strings/yard/code_objects.rb @@ -4,4 +4,5 @@ module PuppetStrings::Yard::CodeObjects require 'puppet-strings/yard/code_objects/defined_type' require 'puppet-strings/yard/code_objects/type' require 'puppet-strings/yard/code_objects/provider' + require 'puppet-strings/yard/code_objects/function' end diff --git a/lib/puppet-strings/yard/code_objects/function.rb b/lib/puppet-strings/yard/code_objects/function.rb new file mode 100644 index 0000000..695b4aa --- /dev/null +++ b/lib/puppet-strings/yard/code_objects/function.rb @@ -0,0 +1,75 @@ +require 'puppet-strings/yard/code_objects/group' + +# Implements the group for Puppet functions. +class PuppetStrings::Yard::CodeObjects::Functions < PuppetStrings::Yard::CodeObjects::Group + # Gets the singleton instance of the group. + # @param [Symbol] type The function type to get the group for. + # @return Returns the singleton instance of the group. + def self.instance(type) + super("puppet_functions_#{type}".intern) + end + + # Gets the display name of the group. + # @param [Boolean] prefix whether to show a prefix. Ignored for Puppet group namespaces. + # @return [String] Returns the display name of the group. + def name(prefix = false) + 'Puppet Functions' + end +end + +# Implements the Puppet function code object. +class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObjects::Base + # Identifier for 3.x Ruby API functions + RUBY_3X = :ruby3x + # Identifier for 4.x Ruby API functions + RUBY_4X = :ruby4x + # Identifier for Puppet language functions + PUPPET = :puppet + + attr_accessor :parameters + + # Initializes a Puppet function code object. + # @param [String] name The name of the function. + # @param [Symbol] function_type The type of function (e.g. :ruby3x, :ruby4x, :puppet) + # @return [void] + def initialize(name, function_type) + super(PuppetStrings::Yard::CodeObjects::Functions.instance(function_type), name) + @parameters = [] + @function_type = function_type + end + + # Gets the type of the code object. + # @return Returns the type of the code object. + def type + :puppet_function + end + + # Gets the function type display string. + # @return Returns the function type display string. + def function_type + case @function_type + when RUBY_3X + 'Ruby 3.x API' + when RUBY_4X + 'Ruby 4.x API' + else + 'Puppet Language' + end + end + + # Gets the Puppet signature of the function. + # @return [String] Returns the Puppet signature of the function. + def signature + tags = self.tags(:param) + args = @parameters.map do |parameter| + name, default = parameter + tag = tags.find { |tag| tag.name == name } if tags + type = tag && tag.types ? "#{tag.type} " : 'Any ' + prefix = "#{name[0]}" if name.start_with?('*', '&') + name = name[1..-1] if prefix + default = " = #{default}" if default + "#{type}#{prefix}$#{name}#{default}" + end.join(', ') + @name.to_s + '(' + args + ')' + end +end diff --git a/lib/puppet-strings/yard/handlers.rb b/lib/puppet-strings/yard/handlers.rb index 655e309..8168343 100644 --- a/lib/puppet-strings/yard/handlers.rb +++ b/lib/puppet-strings/yard/handlers.rb @@ -4,11 +4,13 @@ module PuppetStrings::Yard::Handlers module Ruby require 'puppet-strings/yard/handlers/ruby/type_handler' require 'puppet-strings/yard/handlers/ruby/provider_handler' + require 'puppet-strings/yard/handlers/ruby/function_handler' end # The module for custom Puppet YARD handlers. module Puppet require 'puppet-strings/yard/handlers/puppet/class_handler' require 'puppet-strings/yard/handlers/puppet/defined_type_handler' + require 'puppet-strings/yard/handlers/puppet/function_handler' end end diff --git a/lib/puppet-strings/yard/handlers/puppet/function_handler.rb b/lib/puppet-strings/yard/handlers/puppet/function_handler.rb new file mode 100644 index 0000000..fbb9f56 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/puppet/function_handler.rb @@ -0,0 +1,42 @@ +require 'puppet-strings/yard/handlers/puppet/base' +require 'puppet-strings/yard/parsers' +require 'puppet-strings/yard/code_objects' + +# Implements the handler for Puppet classes. +class PuppetStrings::Yard::Handlers::Puppet::FunctionHandler < PuppetStrings::Yard::Handlers::Puppet::Base + handles PuppetStrings::Yard::Parsers::Puppet::FunctionStatement + + process do + # Register the object + object = PuppetStrings::Yard::CodeObjects::Function.new(statement.name, PuppetStrings::Yard::CodeObjects::Function::PUPPET) + object.source = statement.source + object.source_type = parser.parser_type + register object + + # Log a warning if missing documentation + log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + + # Set the parameter tag types + set_parameter_types(object) + + # Add a return tag + add_return_tag(object) + + # Set the parameters on the object + object.parameters = statement.parameters.map { |p| [p.name, p.value] } + + # Mark the class as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def add_return_tag(object) + tag = object.tag(:return) + if tag + tag.types = ['Any'] unless tag.types + return + end + log.warn "Missing @return tag near #{statement.file}:#{statement.line}." + object.add_tag YARD::Tags::Tag.new(:return, '', 'Any') + end +end diff --git a/lib/puppet-strings/yard/handlers/ruby/function_handler.rb b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb new file mode 100644 index 0000000..65c1420 --- /dev/null +++ b/lib/puppet-strings/yard/handlers/ruby/function_handler.rb @@ -0,0 +1,357 @@ +require 'puppet-strings/yard/handlers/ruby/base' +require 'puppet-strings/yard/code_objects' +require 'puppet/util/docs' + +# Implements the handler for Puppet functions written in Ruby. +class PuppetStrings::Yard::Handlers::Ruby::FunctionHandler < PuppetStrings::Yard::Handlers::Ruby::Base + # Represents the list of Puppet 4.x function API methods to support. + DISPATCH_METHOD_NAMES = %w( + param + required_param + optional_param + repeated_param + optional_repeated_param + required_repeated_param + block_param + required_block_param + optional_block_param + ).freeze + + namespace_only + handles method_call(:create_function) + handles method_call(:newfunction) + + process do + # Only accept calls to Puppet::Functions (4.x) or Puppet::Parser::Functions (3.x) + return unless statement.count > 1 + module_name = statement[0].source + return unless module_name == 'Puppet::Functions' || module_name == 'Puppet::Parser::Functions' + + # Create and register the function object + is_3x = module_name == 'Puppet::Parser::Functions' + object = PuppetStrings::Yard::CodeObjects::Function.new( + get_name, + is_3x ? PuppetStrings::Yard::CodeObjects::Function::RUBY_3X : PuppetStrings::Yard::CodeObjects::Function::RUBY_4X + ) + object.source = statement + register object + + # For 3x, parse the doc parameter for the docstring + # This must be done after the `register` call above because `register` always uses the statement's docstring + if is_3x + docstring = get_3x_docstring(object.name) + register_docstring(object, docstring, nil) if docstring + + # Default any typeless param tag to 'Any' + object.tags(:param).each do |tag| + tag.types = ['Any'] unless tag.types && !tag.types.empty? + end + + # Populate the parameters and the return tag + object.parameters = object.tags(:param).map{ |p| [p.name, nil] } + add_return_tag(object, statement.file, statement.line) + else + # For 4x, auto generate tags based on dispatch docstrings + add_tags(object) + end + + # Mark the function as public if it doesn't already have an api tag + object.add_tag YARD::Tags::Tag.new(:api, 'public') unless object.has_tag? :api + end + + private + def get_name + parameters = statement.parameters(false) + raise YARD::Parser::UndocumentableError, "Expected at least one parameter to Puppet::Functions.create_function at #{statement.file}:#{statement.line}." if parameters.empty? + name = node_as_string(parameters.first) + raise YARD::Parser::UndocumentableError, "Expected a symbol or string literal for first parameter but found '#{parameters.first.type}' at #{statement.file}:#{statement.line}." unless name + name + end + + def add_tags(object) + log.warn "Missing documentation for Puppet function '#{object.name}' at #{statement.file}:#{statement.line}." if object.docstring.empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @param tags near #{object.file}:#{object.line}: parameter documentation should be made on the dispatch call." unless object.tags(:param).empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @return tags near #{object.file}:#{object.line}: return value documentation should be made on the dispatch call." unless object.tags(:return).empty? + log.warn "The docstring for Puppet 4.x function '#{object.name}' contains @overload tags near #{object.file}:#{object.line}: overload tags are automatically generated from the dispatch calls." unless object.tags(:overload).empty? + + # Delete any existing param/return/overload tags + object.docstring.delete_tags(:param) + object.docstring.delete_tags(:return) + object.docstring.delete_tags(:overload) + + block = statement.block + return unless block && block.count >= 2 + + # Get the unqualified name of the Puppet function + unqualified_name = object.name.to_s.split('::').last + + # Walk the block statements looking for dispatch calls and methods with the same name as the Puppet function + default = nil + block[1].children.each do |node| + if node.is_a?(YARD::Parser::Ruby::MethodCallNode) + add_overload_tag(object, node) + elsif node.is_a?(YARD::Parser::Ruby::MethodDefinitionNode) + default = node if node.method_name && node.method_name.source == unqualified_name + end + end + + # Create an overload for the default method if there is one + overloads = object.tags(:overload) + if overloads.empty? && default + add_method_overload(object, default) + overloads = object.tags(:overload) + end + + # If there's only one overload, move the tags to the object itself + if overloads.count == 1 + overload = overloads.first + object.parameters = overload.parameters + object.add_tag(*overload.tags) + object.docstring.delete_tags(:overload) + end + end + + def add_overload_tag(object, node) + # Look for a call to a dispatch method with a block + return unless node.is_a?(YARD::Parser::Ruby::MethodCallNode) && + node.method_name && + node.method_name.source == 'dispatch' && + node.parameters(false).count == 1 && + node.block && + node.block.count >= 2 + + overload_tag = PuppetStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '') + param_tags = overload_tag.tags(:param) + + block = nil + node.block[1].children.each do |child| + next unless child.is_a?(YARD::Parser::Ruby::MethodCallNode) && child.method_name + + method_name = child.method_name.source + next unless DISPATCH_METHOD_NAMES.include?(method_name) + + # Check for block + if method_name.include?('block') + if block + log.warn "A duplicate block parameter was found for Puppet function '#{object.name}' at #{child.file}:#{child.line}." + next + end + + # Store the block; needs to be appended last + block = child + next + end + + # Ensure two parameters to parameter definition + parameters = child.parameters(false) + unless parameters.count == 2 + log.warn "Expected 2 arguments to '#{method_name}' call at #{child.file}:#{child.line}: parameter information may not be correct." + next + end + + add_param_tag( + overload_tag, + param_tags, + node_as_string(parameters[1]), + child.file, + child.line, + node_as_string(parameters[0]), + nil, # TODO: determine default from corresponding Ruby method signature? + method_name.include?('optional'), + method_name.include?('repeated') + ) + end + + # Handle the block parameter after others so it appears last in the list + if block + parameters = block.parameters(false) + if parameters.empty? + name = 'block' + type = 'Callable' + elsif parameters.count == 1 + name = node_as_string(parameters[0]) + type = 'Callable' + elsif parameters.count == 2 + type = node_as_string(parameters[0]) + name = node_as_string(parameters[1]) + else + log.warn "Unexpected number of arguments to block definition at #{block.file}:#{block.line}." + end + + if name && type + add_param_tag( + overload_tag, + param_tags, + name, + block.file, + block.line, + type, + nil, # TODO: determine default from corresponding Ruby method signature? + block.method_name.source.include?('optional'), + false, # Not repeated + true # Is block + ) + end + end + + # Add a return tag if missing + add_return_tag(overload_tag, node.file, node.line) + + # Validate that tags have parameters + validate_overload(overload_tag, node.file, node.line) + + object.add_tag overload_tag + end + + def add_method_overload(object, node) + overload_tag = PuppetStrings::Yard::Tags::OverloadTag.new(object.name, node.docstring || '') + param_tags = overload_tag.tags(:param) + + parameters = node.parameters + + # Populate the required parameters + params = parameters.unnamed_required_params + if params + params.each do |parameter| + add_param_tag( + overload_tag, + param_tags, + parameter.source, + parameter.file, + parameter.line + ) + end + end + + # Populate the optional parameters + params = parameters.unnamed_optional_params + if params + params.each do |parameter| + add_param_tag( + overload_tag, + param_tags, + parameter[0].source, + parameter.file, + parameter.line, + nil, + parameter[1].source, + true + ) + end + end + + # Populate the splat parameter + param = parameters.splat_param + if param + add_param_tag( + overload_tag, + param_tags, + param.source, + param.file, + param.line, + nil, + nil, + false, + true + ) + end + + # Populate the block parameter + param = parameters.block_param + if param + add_param_tag( + overload_tag, + param_tags, + param.source, + param.file, + param.line, + nil, + nil, + false, + false, + true + ) + end + + # Add a return tag if missing + add_return_tag(overload_tag, node.file, node.line) + + # Validate that tags have parameters + validate_overload(overload_tag, node.file, node.line) + + object.add_tag overload_tag + end + + def add_param_tag(object, tags, name, file, line, type = nil, default = nil, optional = false, repeated = false, block = false) + tag = tags.find { |tag| tag.name == name } if tags + log.warn "Missing @param tag for parameter '#{name}' near #{file}:#{line}." unless tag || object.docstring.all.empty? + log.warn "The @param tag for parameter '#{name}' should not contain a type specification near #{file}:#{line}: ignoring in favor of dispatch type information." if type && tag && tag.types && !tag.types.empty? + + if repeated + name = '*' + name + elsif block + name = '&' + name + end + + unless type + type = tag && tag.types ? tag.type : 'Any' + end + type = optional ? "Optional[#{type}]" : type + + object.parameters << [name, to_puppet_literal(default)] + + if tag + tag.name = name + tag.types = [type] + else + object.add_tag YARD::Tags::Tag.new(:param, '', type, name) + end + end + + def add_return_tag(object, file, line) + tag = object.tag(:return) + if tag + tag.types = ['Any'] unless tag.types + return + end + log.warn "Missing @return tag near #{file}:#{line}." + object.add_tag YARD::Tags::Tag.new(:return, '', 'Any') + end + + def validate_overload(overload, file, line) + # Validate that tags have matching parameters + overload.tags(:param).each do |tag| + next if overload.parameters.find { |p| tag.name == p[0] } + log.warn "The @param tag for parameter '#{tag.name}' has no matching parameter at #{file}:#{line}." + end + end + + def get_3x_docstring(name) + parameters = statement.parameters(false) + if parameters.count >= 2 + parameters[1].each do |kvp| + next unless kvp.count == 2 + next unless node_as_string(kvp[0]) == 'doc' + docstring = node_as_string(kvp[1]) + + log.error "Failed to parse docstring for 3.x Puppet function '#{name}' near #{statement.file}:#{statement.line}." and return nil unless docstring + return Puppet::Util::Docs.scrub(docstring) + end + end + + # Log a warning for missing docstring + log.warn "Missing documentation for Puppet function '#{name}' at #{statement.file}:#{statement.line}." + nil + end + + def to_puppet_literal(literal) + case literal + when 'nil' + 'undef' + when ':default' + 'default' + else + literal + end + end +end diff --git a/lib/puppet-strings/yard/tags.rb b/lib/puppet-strings/yard/tags.rb index ed0ffa9..dd46c76 100644 --- a/lib/puppet-strings/yard/tags.rb +++ b/lib/puppet-strings/yard/tags.rb @@ -2,4 +2,5 @@ module PuppetStrings::Yard::Tags require 'puppet-strings/yard/tags/parameter_directive' require 'puppet-strings/yard/tags/property_directive' + require 'puppet-strings/yard/tags/overload_tag' end diff --git a/lib/puppet-strings/yard/tags/overload_tag.rb b/lib/puppet-strings/yard/tags/overload_tag.rb new file mode 100644 index 0000000..50a505e --- /dev/null +++ b/lib/puppet-strings/yard/tags/overload_tag.rb @@ -0,0 +1,94 @@ +# Implements an overload tag for Puppet functions +# +# This differs from Yard's overload tag in that the signatures are formatted according to Puppet language rules. +class PuppetStrings::Yard::Tags::OverloadTag < YARD::Tags::Tag + attr_reader :parameters, :docstring + + # Initializes the overload tag. + # @param [String, Symbol] name The name of the function being overloaded. + # @param [String] docstring The docstring for the overload. + # @return [void] + def initialize(name, docstring) + super(:overload, nil) + @name = name.to_s + @parameters = [] + @docstring = YARD::Docstring.new(docstring) + end + + # Gets the signature of the overload. + # @return [String] Returns the signature of the overload. + def signature + tags = self.tags(:param) + args = @parameters.map do |parameter| + name, default = parameter + tag = tags.find { |tag| tag.name == name } if tags + type = tag && tag.types ? "#{tag.type} " : 'Any ' + prefix = "#{name[0]}" if name.start_with?('*', '&') + name = name[1..-1] if prefix + default = " = #{default}" if default + "#{type}#{prefix}$#{name}#{default}" + end.join(', ') + @name + '(' + args + ')' + end + + # Adds a tag to the overload's docstring. + # @param [YARD::Tag] tag The tag to add to the overload's docstring. + # @return [void] + def add_tag(tag) + @docstring.add_tag(tag) + end + + # Gets the first tag of the given name. + # @param [String, Symbol] name The name of the tag. + # @return [YARD::Tag] Returns the first tag if found or nil if not found. + def tag(name) + @docstring.tag(name) + end + + # Gets all tags or tags of a given name. + # @param [String, Symbol] name The name of the tag to get or nil for all tags. + # @return [Array] Returns an array of tags. + def tags(name = nil) + @docstring.tags(name) + end + + # Determines if a tag with the given name is present. + # @param [String, Symbol] name The tag name. + # @return [Boolean] Returns true if there is at least one tag with the given name or false if not. + def has_tag?(name) + @docstring.has_tag?(name) + end + + # Sets the object associated with this tag. + # @param [Object] value The object to associate with this tag. + # @return [void] + def object=(value) + super(value) + @docstring.object = value + @docstring.tags.each {|tag| tag.object = value } + end + + # Responsible for forwarding method calls to the associated object. + # @param [Symbol] method_name The method being invoked. + # @param [Array] args The args passed to the method. + # @param block The block passed to the method. + # @return Returns what the method call on the object would return. + def method_missing(method_name, *args, &block) + return object.send(method_name, *args, &block) if object.respond_to? method_name + super + end + + # Determines if the associated object responds to the give missing method name. + # @param [Symbol, String] method_name The name of the method to check. + # @param [Boolean] include_all True to include all methods in the check or false for only public methods. + # @return [Boolean] Returns true if the object responds to the method or false if not. + def respond_to_missing?(method_name, include_all = false) + object.respond_to?(method_name, include_all) || super + end + + # Gets the type of the object associated with this tag. + # @return [Symbol] Returns the type of the object associated with this tag. + def type + object.type + end +end diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb new file mode 100644 index 0000000..237a747 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/full_list_puppet_function.erb @@ -0,0 +1,10 @@ +<% even = false %> +<% @items.each do |item| %> +
  • +
    + <%= linkify item, h(item.name(false)) %> + <%= item.function_type %> +
    +
  • + <% even = !even %> +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb index cdc18c5..a71e117 100644 --- a/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/fulldoc/html/setup.rb @@ -34,6 +34,15 @@ def generate_puppet_provider_list generate_list_contents end +# Generates the searchable Puppet function list. +# @return [void] +def generate_puppet_function_list + @items = Registry.all(:puppet_function).sort_by {|f| f.name.to_s } + @list_title = 'Puppet Function List' + @list_type = 'puppet_function' + generate_list_contents +end + # Generates the searchable Ruby method list. # @return [void] def generate_method_list diff --git a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb index ac5c815..afc6356 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/objects.erb +++ b/lib/puppet-strings/yard/templates/default/layout/html/objects.erb @@ -21,6 +21,8 @@ (<%= obj.namespace.path %>) <% elsif obj.type == :puppet_provider %> (Resource type: <%= obj.type_name %>) + <% elsif obj.type == :puppet_function %> + (<%= obj.function_type %>) <% end %> <% end %> diff --git a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb index 91a79ac..703d2f5 100644 --- a/lib/puppet-strings/yard/templates/default/layout/html/setup.rb +++ b/lib/puppet-strings/yard/templates/default/layout/html/setup.rb @@ -4,7 +4,7 @@ def init case object when '_index.html' @page_title = options.title - sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :files, :objects]]] + sections :layout, [:index, [:listing, [:classes, :defined_types, :types, :providers, :functions, :files, :objects]]] else super end @@ -42,6 +42,10 @@ def layout @nav_url = url_for_list('puppet_provider') @page_title = "Provider: #{object.name}" @path = object.path + when PuppetStrings::Yard::CodeObjects::Function + @nav_url = url_for_list('puppet_function') + @page_title = "Puppet Function: #{object.name} (#{object.function_type})" + @path = object.path else @path = object.path end @@ -73,6 +77,11 @@ def create_menu_lists title: 'Providers', search_title: 'Providers' }, + { + type: 'puppet_function', + title: 'Puppet Functions', + search_title: 'Puppet Functions' + }, { type: 'class', title: 'Ruby Classes', @@ -146,6 +155,14 @@ def providers erb(:objects) end +# Renders the functions section. +# @return [String] Returns the rendered section. +def functions + @title = 'Puppet Function Listing A-Z' + @objects_by_letter = objects_by_letter(:puppet_function) + erb(:objects) +end + # Renders the objects section. # @return [String] Returns the rendered section. def objects diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb new file mode 100644 index 0000000..3f1bd40 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/box_info.erb @@ -0,0 +1,14 @@ +
    +
    +
    Defined in:
    +
    + <%= object.file %><% if object.files.size > 1 %>,
    + <%= object.files[1..-1].map {|f| f.first }.join(",
    ") %>
    + <% end %> + + +
    +
    Function type:
    +
    <%= object.function_type %>
    +
    + diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb new file mode 100644 index 0000000..db96389 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/header.erb @@ -0,0 +1 @@ +

    Puppet Function: <%= object.name %>

    diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb new file mode 100644 index 0000000..8cd6ca4 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/overview.erb @@ -0,0 +1,18 @@ +

    Overview

    +
    + <% unless object.has_tag? :overload %> +
    + + + <%= "#{h(object.signature)} ⇒ #{signature_types(object, false)}" %> + + +
    + <% end %> +
    +
    + <%= htmlify(object.docstring) %> +
    +
    + <%= yieldall %> +
    diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb b/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb new file mode 100644 index 0000000..d20b4b6 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/setup.rb @@ -0,0 +1,5 @@ +# Initializes the template. +# @return [void] +def init + sections :header, :box_info, :overview, [T('tags'), :source] +end diff --git a/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb b/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb new file mode 100644 index 0000000..0fd3c5e --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/puppet_function/html/source.erb @@ -0,0 +1,12 @@ +
    + + + + + +
    +
    <%= "\n\n\n" %><%= h format_lines(object) %>
    +
    +
    # File '<%= h object.file %>'<% if object.line %>, line <%= object.line %><% end %><%= "\n\n" %><%= html_syntax_highlight object.source %>
    +
    +
    diff --git a/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb b/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb new file mode 100644 index 0000000..3d12d59 --- /dev/null +++ b/lib/puppet-strings/yard/templates/default/tags/html/puppet_overload.erb @@ -0,0 +1,12 @@ +<% if object.has_tag?(:overload) && object.tags(:overload).any? {|o| !o.docstring.blank? } %> +

    Overloads:

    +
      + <% object.tags(:overload).each_with_index do |overload, index| %> + <% next if overload.docstring.blank? %> +
    • + <%= "#{h(overload.signature)} ⇒ #{signature_types(overload, false)}" %> + <%= yieldall :object => overload %> +
    • + <% end %> +
    +<% end %> diff --git a/lib/puppet-strings/yard/templates/default/tags/setup.rb b/lib/puppet-strings/yard/templates/default/tags/setup.rb index 2166fdf..888d05a 100644 --- a/lib/puppet-strings/yard/templates/default/tags/setup.rb +++ b/lib/puppet-strings/yard/templates/default/tags/setup.rb @@ -4,5 +4,12 @@ def param tag(:param) if object.type == :method || object.type == :puppet_class || - object.type == :puppet_defined_type + object.type == :puppet_defined_type || + object.type == :puppet_function +end + +# Renders the overload section. +# @return [String] Returns the rendered section. +def overload + erb(if object.type == :puppet_function then :puppet_overload else :overload end) end From 1be391ee87949c883292fb2bd9133e636f9f8602 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 12:40:34 -0700 Subject: [PATCH 11/15] (PDOC-63) Implement JSON output. This commit implements the JSON output for Puppet strings. --- lib/puppet-strings.rb | 3 +- lib/puppet-strings/json.rb | 50 +++++++++++++++++++ lib/puppet-strings/yard/code_objects/class.rb | 15 ++++++ .../yard/code_objects/defined_type.rb | 14 ++++++ .../yard/code_objects/function.rb | 20 +++++++- .../yard/code_objects/provider.rb | 16 ++++++ lib/puppet-strings/yard/code_objects/type.rb | 36 +++++++++++++ lib/puppet-strings/yard/tags/overload_tag.rb | 15 ++++++ 8 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 lib/puppet-strings/json.rb diff --git a/lib/puppet-strings.rb b/lib/puppet-strings.rb index f2cbdfc..410d92b 100644 --- a/lib/puppet-strings.rb +++ b/lib/puppet-strings.rb @@ -47,7 +47,8 @@ module PuppetStrings # If outputting JSON, render the output if render_as_json - # TODO: implement + require 'puppet-strings/json' + PuppetStrings::Json.render(json_file) end end diff --git a/lib/puppet-strings/json.rb b/lib/puppet-strings/json.rb new file mode 100644 index 0000000..32b8d52 --- /dev/null +++ b/lib/puppet-strings/json.rb @@ -0,0 +1,50 @@ +require 'json' + +# The module for JSON related functionality. +module PuppetStrings::Json + + # Renders the current YARD registry as JSON to the given file (or STDOUT if nil). + # @param [String] file The path to the output file to render the registry to. If nil, output will be to STDOUT. + # @return [void] + def self.render(file = nil) + document = { + puppet_classes: YARD::Registry.all(:puppet_class).sort_by! { |c| c.name }.map! { |c| c.to_hash }, + defined_types: YARD::Registry.all(:puppet_defined_type).sort_by! { |dt| dt.name }.map! { |dt| dt.to_hash }, + resource_types: YARD::Registry.all(:puppet_type).sort_by! { |t| t.name }.map! { |t| t.to_hash }, + providers: YARD::Registry.all(:puppet_provider).sort_by! { |p| p.name }.map! { |p| p.to_hash }, + puppet_functions: YARD::Registry.all(:puppet_function).sort_by! { |f| f.name }.map! { |f| f.to_hash }, + # TODO: Need Ruby documentation? + } + + if file + File.open(file, 'w') do |f| + f.write(JSON.pretty_generate(document)) + f.write("\n") + end + else + puts JSON.pretty_generate(document) + end + end + + # Converts a YARD::Docstring (or String) to a docstring hash for JSON output. + # @param [YARD::Docstring, String] docstring The docstring to convert to a hash. + # @return [Hash] Returns a hash representation of the given docstring. + def self.docstring_to_hash(docstring) + hash = {} + hash[:text] = docstring + if docstring.is_a? YARD::Docstring + # Skip over the API tags that are public + tags = docstring.tags.select { |t| t.tag_name != 'api' || t.text != 'public' }.map do |t| + next t.to_hash if t.respond_to?(:to_hash) + + tag = { tag_name: t.tag_name } + tag[:text] = t.text if t.text + tag[:types] = t.types if t.types + tag[:name] = t.name if t.name + tag + end + hash[:tags] = tags unless tags.empty? + end + hash + end +end diff --git a/lib/puppet-strings/yard/code_objects/class.rb b/lib/puppet-strings/yard/code_objects/class.rb index 71461c5..121ebd2 100644 --- a/lib/puppet-strings/yard/code_objects/class.rb +++ b/lib/puppet-strings/yard/code_objects/class.rb @@ -41,4 +41,19 @@ class PuppetStrings::Yard::CodeObjects::Class < PuppetStrings::Yard::CodeObjects def source @statement.source end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:file] = file + hash[:line] = line + hash[:inherits] = statement.parent_class if statement.parent_class + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten] + hash[:defaults] = defaults unless defaults.empty? + hash[:source] = source unless source && source.empty? + hash + end end diff --git a/lib/puppet-strings/yard/code_objects/defined_type.rb b/lib/puppet-strings/yard/code_objects/defined_type.rb index 12d4afb..e9088c1 100644 --- a/lib/puppet-strings/yard/code_objects/defined_type.rb +++ b/lib/puppet-strings/yard/code_objects/defined_type.rb @@ -41,4 +41,18 @@ class PuppetStrings::Yard::CodeObjects::DefinedType < PuppetStrings::Yard::CodeO def source @statement.source end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:file] = file + hash[:line] = line + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten] + hash[:defaults] = defaults unless defaults.empty? + hash[:source] = source unless source && source.empty? + hash + end end diff --git a/lib/puppet-strings/yard/code_objects/function.rb b/lib/puppet-strings/yard/code_objects/function.rb index 695b4aa..f295d29 100644 --- a/lib/puppet-strings/yard/code_objects/function.rb +++ b/lib/puppet-strings/yard/code_objects/function.rb @@ -57,9 +57,10 @@ class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObje end end - # Gets the Puppet signature of the function. + # Gets the Puppet signature of the function (single overload only). # @return [String] Returns the Puppet signature of the function. def signature + return '' if self.has_tag? :overload tags = self.tags(:param) args = @parameters.map do |parameter| name, default = parameter @@ -72,4 +73,21 @@ class PuppetStrings::Yard::CodeObjects::Function < PuppetStrings::Yard::CodeObje end.join(', ') @name.to_s + '(' + args + ')' end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:file] = file + hash[:line] = line + hash[:type] = @function_type.to_s + signature = self.signature + hash[:signature] = signature unless signature.empty? + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten] + hash[:defaults] = defaults unless defaults.empty? + hash[:source] = source unless source && source.empty? + hash + end end diff --git a/lib/puppet-strings/yard/code_objects/provider.rb b/lib/puppet-strings/yard/code_objects/provider.rb index 8a30075..06a4f1b 100644 --- a/lib/puppet-strings/yard/code_objects/provider.rb +++ b/lib/puppet-strings/yard/code_objects/provider.rb @@ -74,4 +74,20 @@ class PuppetStrings::Yard::CodeObjects::Provider < PuppetStrings::Yard::CodeObje @commands ||= {} @commands[key] = value end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:type_name] = type_name + hash[:file] = file + hash[:line] = line + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + hash[:confines] = confines if confines && !confines.empty? + hash[:features] = features if features && !features.empty? + hash[:defaults] = defaults if defaults && !defaults.empty? + hash[:commands] = commands if commands && !commands.empty? + hash + end end diff --git a/lib/puppet-strings/yard/code_objects/type.rb b/lib/puppet-strings/yard/code_objects/type.rb index bf80e14..8e3185e 100644 --- a/lib/puppet-strings/yard/code_objects/type.rb +++ b/lib/puppet-strings/yard/code_objects/type.rb @@ -50,6 +50,19 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects: @values << new unless @values.include? new @aliases[new] = old end + + # Converts the parameter to a hash representation. + # @return [Hash] Returns a hash representation of the parameter. + def to_hash + hash = {} + hash[:name] = name + hash[:description] = docstring unless docstring.empty? + hash[:values] = values unless values.empty? + hash[:aliases] = aliases unless aliases.empty? + hash[:isnamevar] = true if isnamevar + hash[:default] = default if default + hash + end end # Represents a resource type property (same attributes as a parameter). @@ -67,6 +80,15 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects: @name = name @docstring = docstring end + + # Converts the feature to a hash representation. + # @return [Hash] Returns a hash representation of the feature. + def to_hash + hash = {} + hash[:name] = name + hash[:description] = docstring unless docstring.empty? + hash + end end attr_reader :properties, :parameters, :features @@ -107,4 +129,18 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects: @features ||= [] @features << feature end + + # Converts the code object to a hash representation. + # @return [Hash] Returns a hash representation of the code object. + def to_hash + hash = {} + hash[:name] = name + hash[:file] = file + hash[:line] = line + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) + hash[:properties] = properties.map { |p| p.to_hash } if properties && !properties.empty? + hash[:parameters] = parameters.map { |p| p.to_hash } if parameters && !parameters.empty? + hash[:features] = features.map { |f| f.to_hash } if features && !features.empty? + hash + end end diff --git a/lib/puppet-strings/yard/tags/overload_tag.rb b/lib/puppet-strings/yard/tags/overload_tag.rb index 50a505e..84ce878 100644 --- a/lib/puppet-strings/yard/tags/overload_tag.rb +++ b/lib/puppet-strings/yard/tags/overload_tag.rb @@ -91,4 +91,19 @@ class PuppetStrings::Yard::Tags::OverloadTag < YARD::Tags::Tag def type object.type end + + # Converts the overload tag to a hash representation. + # @return [Hash] Returns a hash representation of the overload. + def to_hash + hash = {} + hash[:tag_name] = tag_name + hash[:text] = text if text + hash[:signature] = signature + hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) if !docstring.empty? + defaults = Hash[*parameters.select{ |p| !p[1].nil? }.flatten] + hash[:defaults] = defaults unless defaults.empty? + hash[:types] = types if types + hash[:name] = name if name + hash + end end From f2aa7d00c50d26d4e86a1ba43039c703d27ef247 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Sun, 11 Sep 2016 14:46:57 -0700 Subject: [PATCH 12/15] (PDOC-63) Implement the Puppet Strings rake tasks. This commit implements the `strings:generate` and `strings:gh_pages:update` rake tasks. The `strings:generate` task is responsible for generating Puppet Strings documentation. The `strings:gh_pages:update` task is responsible for updating the `gh_pages` branch of a GitHub repository with the latest Puppet Strings documentation. --- README.md | 54 +++++++++++++++------------- Rakefile | 4 +++ lib/puppet-strings/tasks.rb | 10 ++++++ lib/puppet-strings/tasks/generate.rb | 23 ++++++++++++ lib/puppet-strings/tasks/gh_pages.rb | 43 ++++++++++++++++++++++ 5 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 lib/puppet-strings/tasks.rb create mode 100644 lib/puppet-strings/tasks/generate.rb create mode 100644 lib/puppet-strings/tasks/gh_pages.rb diff --git a/README.md b/README.md index d087e6b..709fdcf 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ Puppet Strings -============= +============== [![Build Status](https://travis-ci.org/puppetlabs/puppet-strings.png?branch=master)](https://travis-ci.org/puppetlabs/puppet-strings) [![Gem Version](https://badge.fury.io/rb/puppet-strings.svg)](https://badge.fury.io/rb/puppet-strings) A Puppet Face and plugin built on the [YARD Documentation Tool](http://yardoc.org/) and the Puppet 4 Parser. It is uses YARD and the Puppet Parser to generate HTML documentation about Puppet code and Puppet extensions written in Ruby. It will eventually replace the `puppet doc` command once feature parity has been achieved. - | | | | -------------- |------------------------------------------------------------ | | *Code* | [GitHub][repo] | @@ -193,44 +192,51 @@ Here are a few other good resources for getting started with documentation: * [YARD Tags Overview](http://www.rubydoc.info/gems/yard/file/docs/Tags.md) Rake Tasks ------ +---------- -This module is also available as a Gem and makes three rake tasks (`strings:generate`, `strings:serve`, and `strings:gh_pages`) available in `puppet-strings/rake_tasks`. To add this to your module's CI workflow, be sure to add this module to your `Gemfile`: +Puppet Strings comes with two rake tasks: `strings:generate` and `strings:gh_pages:update` available in `puppet-strings/tasks`. -In addition to generating the usual 'doc' directory of HTML documentation, the `strings:generate` rake task will also drop a strings.json file containing a JSON representation of the module into the directory the rake task was run from. +Add the following to your Gemfile to use `puppet-strings`: ```ruby gem 'puppet-strings', :git => 'https://github.com/puppetlabs/puppet-strings.git' ``` -To use the rake tasks, `require puppet-strings/rake_tasks` in your `Rakefile`: +In your `Rakefile`, add the following to use the `puppet-strings` tasks: ```ruby -require 'puppet-strings/rake_tasks' +require 'puppet-strings/tasks' ``` -The task `strings:generate` which is provided by including `puppet-strings/rake_tasks` will scan the manifests and lib directory from your single module. If you need to document a complete, or part of a, puppet tree, you can use the `PuppetStrings::RakeTasks::Generate` task. This rake task will by default overwrite strings:generate unless you specify a custom name. See the example below on how you can use it and which options it supports. +The `strings:generate` task can be used to generate documentation: -```ruby -require 'puppet-strings/rake_tasks/generate' - -PuppetStrings::RakeTasks::Generate.new(:documentation) do |task| - task.paths = ['site/roles','site/profiles','modules/internal'] - task.excludes = ['/vendor/','/example/'] - task.options = {} # disables the strings.json output - # module_resourcefiles are the patterns of included files. Below is the default. - # task.module_resourcefiles = ['manifests/**/*.pp', 'lib/**/*.rb'] -end +``` +$ rake strings:generate ``` -The `strings:gh_pages` task will generate your Strings documentation to be made available via [GitHub Pages](https://pages.github.com/). It will: +The task accepts the following parameters: - 1. Create a `doc` directory in the root of your project - 2. Check out the `gh-pages` branch of the current repository in the `doc` directory (it will create a branch if one does not already exist) - 3. Generate strings documentation using the `strings:generate` task - 4. Commit the changes and push them to the `gh-pages` branch **with the `-f` flag** +* `patterns`: the search patterns to use for finding files to document (defaults to `manifests/**/*.pp functions/**/*.pp types/**/*.pp lib/**/*.rb`). +* `debug`: enables debug output when set to `true`. +* `backtrace`: enables backtraces for errors when set to `true`. +* `markup`: the markup language to use (defaults to `markdown`). +* `yard_args`: additional arguments to pass to YARD. -This task aims to keep the `gh-pages` branch up to date with the current code and uses the `-f` flag when pushing to the `gh-pages` branch. Please keep this in mind as it **will be destructive** if not used properly. +An example of passing arguments to the `strings:generate` Rake task: + +``` +$ rake strings:generate\['**/*.pp **/*.rb, true, true, markdown, --readme README.md'] +``` + +The `strings:gh_pages:update` task will generate your Puppet Strings documentation to be made available via [GitHub Pages](https://pages.github.com/). It will: + +1. Create a `doc` directory in the root of your project +2. Check out the `gh-pages` branch of the current repository in the `doc` directory (it will create a branch if one does not already exist) +3. Generate strings documentation using the `strings:generate` task +4. Commit the changes and push them to the `gh-pages` branch **with the `--force` flag** + +This task aims to keep the `gh-pages` branch up to date with the current code and uses the `-f` flag when pushing to the `gh-pages` branch. +***Please note this operation will be destructive if not used properly.*** Developing and Contributing ----- diff --git a/Rakefile b/Rakefile index 459dda0..adb0c64 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,10 @@ require 'rubygems' require 'puppetlabs_spec_helper/rake_tasks' require 'puppet-lint/tasks/puppet-lint' + +# Add our own tasks +require 'puppet-strings/tasks' + PuppetLint.configuration.send('disable_80chars') PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] diff --git a/lib/puppet-strings/tasks.rb b/lib/puppet-strings/tasks.rb new file mode 100644 index 0000000..255ff60 --- /dev/null +++ b/lib/puppet-strings/tasks.rb @@ -0,0 +1,10 @@ +require 'rake' +require 'rake/tasklib' + +module PuppetStrings + # The module for Puppet Strings rake tasks. + module Tasks + require 'puppet-strings/tasks/generate.rb' + require 'puppet-strings/tasks/gh_pages.rb' + end +end diff --git a/lib/puppet-strings/tasks/generate.rb b/lib/puppet-strings/tasks/generate.rb new file mode 100644 index 0000000..616deda --- /dev/null +++ b/lib/puppet-strings/tasks/generate.rb @@ -0,0 +1,23 @@ +require 'puppet-strings' + +# Implements the strings:generate task. +namespace :strings do + desc 'Generate Puppet documentation with YARD.' + task :generate, :patterns, :debug, :backtrace, :markup, :json, :yard_args do |t, args| + patterns = args[:patterns] + patterns = patterns.split if patterns + patterns ||= PuppetStrings::DEFAULT_SEARCH_PATTERNS + + options = { + debug: args[:debug] == 'true', + backtrace: args[:backtrace] == 'true', + markup: args[:markup] || 'markdown', + } + + options[:json] = args[:json] if args.key? :json + options[:yard_args] = args[:yard_args].split if args.key? :yard_args + + PuppetStrings.generate(patterns, options) + end +end + diff --git a/lib/puppet-strings/tasks/gh_pages.rb b/lib/puppet-strings/tasks/gh_pages.rb new file mode 100644 index 0000000..c6b5262 --- /dev/null +++ b/lib/puppet-strings/tasks/gh_pages.rb @@ -0,0 +1,43 @@ +require 'puppet-strings/tasks' + +namespace :strings do + namespace :gh_pages do + desc 'Checkout the gh-pages branch for doc generation.' + task :checkout do + if Dir.exist?('doc') + fail "The 'doc' directory (#{File.expand_path('doc')}) is not a Git repository! Remove it and run the Rake task again." unless Dir.exist?('doc/.git') + Dir.chdir('doc') do + system 'git checkout gh-pages' + system 'git pull --rebase origin gh-pages' + end + else + git_uri = `git config --get remote.origin.url`.strip + fail "Could not determine the remote URL for origin: ensure the current directory is a Git repro with a remote named 'origin'." unless $?.success? + + Dir.mkdir('doc') + Dir.chdir('doc') do + system 'git init' + system "git remote add origin #{git_uri}" + system 'git pull origin gh-pages' + system 'git checkout -b gh-pages' + end + end + end + + desc 'Push new docs to GitHub.' + task :push do + Dir.chdir('doc') do + system 'git add .' + system "git commit -m '[strings] Generated Documentation Update'" + system 'git push origin gh-pages -f' + end + end + + desc 'Run checkout, generate, and push tasks.' + task :update => [ + :checkout, + :'strings:generate', + :push, + ] + end +end From cf77ef1379c4a93143f6a89db7a56037cc192436 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Wed, 14 Sep 2016 12:20:26 -0700 Subject: [PATCH 13/15] (PDOC-63) Add specs to test the new implementation. This commit adds specs to cover parts of the new implementation of Puppet Strings. --- Rakefile | 17 +- .../test/lib/puppet/functions/4x_function.rb | 5 + .../lib/puppet/parser/functions/function3x.rb | 3 + .../fixtures/modules/test/manifests/init.pp | 27 + .../test/manifests/triple_nested_classes.pp | 27 + .../fixtures/modules/test/metadata.json | 6 + acceptance/running_strings_generate.rb | 28 + .../yard/handlers/puppet/base.rb | 2 - spec/acceptance/running_strings_yardoc.rb | 28 - spec/fixtures/unit/json/output.json | 348 ++++++++++ spec/spec_helper.rb | 16 +- spec/spec_helper_acceptance.rb | 5 +- spec/unit/puppet-strings/json_spec.rb | 132 ++++ .../handlers/puppet/class_handler_spec.rb | 155 +++++ .../puppet/defined_type_handler_spec.rb | 155 +++++ .../handlers/puppet/function_handler_spec.rb | 168 +++++ .../handlers/ruby/function_handler_spec.rb | 613 ++++++++++++++++++ .../handlers/ruby/provider_handler_spec.rb | 62 ++ .../yard/handlers/ruby/type_handler_spec.rb | 126 ++++ .../yard/parsers/puppet/parser_spec.rb | 171 +++++ 20 files changed, 2045 insertions(+), 49 deletions(-) create mode 100644 acceptance/fixtures/modules/test/lib/puppet/functions/4x_function.rb create mode 100644 acceptance/fixtures/modules/test/lib/puppet/parser/functions/function3x.rb create mode 100644 acceptance/fixtures/modules/test/manifests/init.pp create mode 100644 acceptance/fixtures/modules/test/manifests/triple_nested_classes.pp create mode 100644 acceptance/fixtures/modules/test/metadata.json create mode 100644 acceptance/running_strings_generate.rb delete mode 100644 spec/acceptance/running_strings_yardoc.rb create mode 100644 spec/fixtures/unit/json/output.json create mode 100644 spec/unit/puppet-strings/json_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb create mode 100644 spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb diff --git a/Rakefile b/Rakefile index adb0c64..fa3dcb1 100644 --- a/Rakefile +++ b/Rakefile @@ -6,17 +6,14 @@ require 'puppet-lint/tasks/puppet-lint' require 'puppet-strings/tasks' PuppetLint.configuration.send('disable_80chars') -PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] +PuppetLint.configuration.ignore_paths = %w(acceptance/**/*.pp spec/**/*.pp pkg/**/*.pp) -desc "Validate manifests, templates, and ruby files" +desc 'Validate Ruby source files and ERB templates.' task :validate do - Dir['manifests/**/*.pp'].each do |manifest| - sh "puppet parser validate --noop #{manifest}" - end Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ end - Dir['templates/**/*.erb'].each do |template| + Dir['lib/puppet-strings/yard/templates/**/*.erb'].each do |template| sh "erb -P -x -T '-' #{template} | ruby -c" end end @@ -32,16 +29,16 @@ task :acceptance do end cli = BeakerHostGenerator::CLI.new([target]) - nodeset_dir = "spec/acceptance/nodesets" + nodeset_dir = 'acceptance/nodesets' nodeset = "#{nodeset_dir}/#{target}.yml" FileUtils.mkdir_p(nodeset_dir) File.open(nodeset, 'w') do |fh| fh.print(cli.execute) end puts nodeset - sh "gem build puppet-strings.gemspec" - sh "puppet module build spec/unit/puppet/examples/test" - sh "BEAKER_set=#{ENV["platform"]} rspec spec/acceptance/*.rb" + sh 'gem build puppet-strings.gemspec' + sh 'puppet module build acceptance/fixtures/modules/test' + sh "BEAKER_set=#{ENV['platform']} rspec acceptance/*.rb" end task(:rubocop) do diff --git a/acceptance/fixtures/modules/test/lib/puppet/functions/4x_function.rb b/acceptance/fixtures/modules/test/lib/puppet/functions/4x_function.rb new file mode 100644 index 0000000..5825496 --- /dev/null +++ b/acceptance/fixtures/modules/test/lib/puppet/functions/4x_function.rb @@ -0,0 +1,5 @@ +# function 4x +# +# This is a function which is used to test puppet strings +Puppet::Functions.create_function(:function4x) do +end diff --git a/acceptance/fixtures/modules/test/lib/puppet/parser/functions/function3x.rb b/acceptance/fixtures/modules/test/lib/puppet/parser/functions/function3x.rb new file mode 100644 index 0000000..e3083ea --- /dev/null +++ b/acceptance/fixtures/modules/test/lib/puppet/parser/functions/function3x.rb @@ -0,0 +1,3 @@ +Puppet::Parser::Functions.newfunction(:function3x, :doc => "This is the +function documentation for `function3x`") do |args| +end diff --git a/acceptance/fixtures/modules/test/manifests/init.pp b/acceptance/fixtures/modules/test/manifests/init.pp new file mode 100644 index 0000000..8ebd451 --- /dev/null +++ b/acceptance/fixtures/modules/test/manifests/init.pp @@ -0,0 +1,27 @@ +# Class: test +# +# This class exists to serve as fixture data for testing the puppet strings face +# +# @example +# class { "test": } +# +# @param package_name The name of the package +# @param service_name The name of the service +class test ( + $package_name = $test::params::package_name, + $service_name = $test::params::service_name, + +) inherits test::params { + + # validate parameters here + + class { 'test::install': } -> + class { 'test::config': } ~> + class { 'test::service': } -> + Class['test'] + + File { + owner => 'user', + path => 'some/file/path', + } +} diff --git a/acceptance/fixtures/modules/test/manifests/triple_nested_classes.pp b/acceptance/fixtures/modules/test/manifests/triple_nested_classes.pp new file mode 100644 index 0000000..6ac95cd --- /dev/null +++ b/acceptance/fixtures/modules/test/manifests/triple_nested_classes.pp @@ -0,0 +1,27 @@ +# Testing tested classes +# docs stuff +# @param nameservers [String] Don't ask me what this does! +# @param default_lease_time [Integer[1024, 8192]] text goes here +# @param max_lease_time does stuff +class outer ( + $dnsdomain, + $nameservers, + $default_lease_time = 3600, + $max_lease_time = 86400 + ) { + # @param options [String[5,7]] gives user choices + # @param multicast [Boolean] foobar + # @param servers yep, that's right + class middle ( + $options = "iburst", + $servers, + $multicast = false + ) { + class inner ( + $choices = "uburst", + $secenekler = "weallburst", + $boxen, + $manyspell = true + ) {} + } +} diff --git a/acceptance/fixtures/modules/test/metadata.json b/acceptance/fixtures/modules/test/metadata.json new file mode 100644 index 0000000..1892d9d --- /dev/null +++ b/acceptance/fixtures/modules/test/metadata.json @@ -0,0 +1,6 @@ +{ + "name": "username-test", + "version": "0.0.1", + "author": "username", + "license": "Apache 2.0" +} diff --git a/acceptance/running_strings_generate.rb b/acceptance/running_strings_generate.rb new file mode 100644 index 0000000..fa13c63 --- /dev/null +++ b/acceptance/running_strings_generate.rb @@ -0,0 +1,28 @@ +require 'spec_helper_acceptance' +require 'json' + +describe 'Generating module documentation using generate action' do + def read_file_on(host, filename) + on(host, "cat #{filename}").stdout + end + + before :all do + modules = JSON.parse(on(master, puppet('module', 'list', '--render-as', 'json')).stdout) + test_module_info = modules['modules_by_path'].values.flatten.find { |mod_info| mod_info =~ /Module test/ } + test_module_path = test_module_info.match(/\(([^)]*)\)/)[1] + + on master, puppet('strings', 'generate', "#{test_module_path}/**/*.{rb,pp}") + end + + it 'should generate documentation for manifests' do + expect(read_file_on(master, '/root/doc/puppet_classes/test.html')).to include('Class: test') + end + + it 'should generate documentation for 3x functions' do + expect(read_file_on(master, '/root/doc/puppet_functions_ruby3x/function3x.html')).to include('This is the function documentation for function3x') + end + + it 'should generate documentation for 4x functions' do + expect(read_file_on(master, '/root/doc/puppet_functions_ruby4x/function4x.html')).to include('This is a function which is used to test puppet strings') + end +end diff --git a/lib/puppet-strings/yard/handlers/puppet/base.rb b/lib/puppet-strings/yard/handlers/puppet/base.rb index 0315b3c..8bcd8d2 100644 --- a/lib/puppet-strings/yard/handlers/puppet/base.rb +++ b/lib/puppet-strings/yard/handlers/puppet/base.rb @@ -23,13 +23,11 @@ class PuppetStrings::Yard::Handlers::Puppet::Base < YARD::Handlers::Base # Assign the types for the parameter statement.parameters.each do |parameter| tag = tags.find { |t| t.name == parameter.name } - unless tag log.warn "Missing @param tag for parameter '#{parameter.name}' near #{statement.file}:#{statement.line}." unless object.docstring.empty? # Add a tag with an empty docstring object.add_tag YARD::Tags::Tag.new(:param, '', [parameter.type || 'Any'], parameter.name) - object.parameters << [parameter.name, parameter.value] next end diff --git a/spec/acceptance/running_strings_yardoc.rb b/spec/acceptance/running_strings_yardoc.rb deleted file mode 100644 index 38b9fd4..0000000 --- a/spec/acceptance/running_strings_yardoc.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'spec_helper_acceptance' -require 'json' - -describe 'Genearting module documation using yardoc action' do - def read_file_on(host, filename) - on(host, "cat #{filename}").stdout - end - - before :all do - modules = JSON.parse(on(master, puppet("module", "list", "--render-as", "json")).stdout) - test_module_info = modules["modules_by_path"].values.flatten.find { |mod_info| mod_info =~ /Module test/ } - test_module_path = test_module_info.match(/\(([^)]*)\)/)[1] - - on master, puppet("strings", "#{test_module_path}/**/*.{rb,pp}") - end - - it "should generate documentation for manifests" do - expect(read_file_on(master, '/root/doc/test.html')).to include("Class: test") - end - - it "should generate documenation for 3x functions" do - expect(read_file_on(master, '/root/doc/Puppet3xFunctions.html')).to include("This is the function documentation for `function3x`") - end - - it "should generate documenation for 4x functions" do - expect(read_file_on(master, '/root/doc/Puppet4xFunctions.html')).to include("This is a function which is used to test puppet strings") - end -end diff --git a/spec/fixtures/unit/json/output.json b/spec/fixtures/unit/json/output.json new file mode 100644 index 0000000..a6d1197 --- /dev/null +++ b/spec/fixtures/unit/json/output.json @@ -0,0 +1,348 @@ +{ + "puppet_classes": [ + { + "name": "klass", + "file": "(stdin)", + "line": 5, + "inherits": "foo::bar", + "docstring": { + "text": "A simple class.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar {\n}" + } + ], + "defined_types": [ + { + "name": "dt", + "file": "(stdin)", + "line": 12, + "docstring": { + "text": "A simple defined type.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "define dt(Integer $param1, $param2, String $param3 = hi) {\n}" + } + ], + "resource_types": [ + { + "name": "database", + "file": "(stdin)", + "line": 43, + "docstring": { + "text": "An example database server resource type." + }, + "properties": [ + { + "name": "ensure", + "description": "What state the database should be in.", + "values": [ + "present", + "absent", + "up", + "down" + ], + "aliases": { + "up": "present", + "down": "absent" + }, + "default": "up" + }, + { + "name": "file", + "description": "The database file to use." + }, + { + "name": "log_level", + "description": "The log level to use.", + "values": [ + "debug", + "warn", + "error" + ], + "default": "warn" + } + ], + "parameters": [ + { + "name": "address", + "description": "The database server name.", + "isnamevar": true + }, + { + "name": "encryption_key", + "description": "The encryption key to use." + }, + { + "name": "encrypt", + "description": "Whether or not to encrypt the database.", + "values": [ + "true", + "false", + "yes", + "no" + ], + "default": "false" + } + ], + "features": [ + { + "name": "encryption", + "description": "The provider supports encryption." + } + ] + } + ], + "providers": [ + { + "name": "linux", + "type_name": "database", + "file": "(stdin)", + "line": 33, + "docstring": { + "text": "An example provider on Linux." + }, + "confines": { + "kernel": "Linux", + "osfamily": "RedHat" + }, + "features": [ + "implements_some_feature", + "some_other_feature" + ], + "defaults": { + "kernel": "Linux" + }, + "commands": { + "foo": "/usr/bin/foo" + } + } + ], + "puppet_functions": [ + { + "name": "func", + "file": "(stdin)", + "line": 20, + "type": "puppet", + "signature": "func(Integer $param1, Any $param2, String $param3 = hi)", + "docstring": { + "text": "A simple function.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "function func(Integer $param1, $param2, String $param3 = hi) {\n}" + }, + { + "name": "func3x", + "file": "(stdin)", + "line": 1, + "type": "ruby3x", + "signature": "func3x(String $first, Any $second)", + "docstring": { + "text": "An example 3.x function.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "String" + ], + "name": "first" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "second" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "source": "Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC\nAn example 3.x function.\n@param [String] first The first parameter.\n@param second The second parameter.\n@return [Undef] Returns nothing.\nDOC\n) do |*args|\nend" + }, + { + "name": "func4x", + "file": "(stdin)", + "line": 11, + "type": "ruby4x", + "docstring": { + "text": "An example 4.x function.", + "tags": [ + { + "tag_name": "overload", + "signature": "func4x(Integer $param1, Any $param2, Optional[Array[String]] $param3)", + "docstring": { + "text": "The first overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "The third parameter.", + "types": [ + "Optional[Array[String]]" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "name": "func4x" + }, + { + "tag_name": "overload", + "signature": "func4x(Boolean $param, Callable &$block)", + "docstring": { + "text": "The second overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Boolean" + ], + "name": "param" + }, + { + "tag_name": "param", + "text": "The block parameter.", + "types": [ + "Callable" + ], + "name": "&block" + }, + { + "tag_name": "return", + "text": "Returns a string.", + "types": [ + "String" + ] + } + ] + }, + "name": "func4x" + } + ] + }, + "source": "Puppet::Functions.create_function(:func4x) do\n # The first overload.\n # @param param1 The first parameter.\n # @param param2 The second parameter.\n # @param param3 The third parameter.\n # @return [Undef] Returns nothing.\n dispatch :foo do\n param 'Integer', :param1\n param 'Any', :param2\n optional_param 'Array[String]', :param3\n end\n\n # The second overload.\n # @param param The first parameter.\n # @param block The block parameter.\n # @return [String] Returns a string.\n dispatch :other do\n param 'Boolean', :param\n block_param\n end\nend" + } + ] +} diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bf10b10..ac86301 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,13 +1,17 @@ -dir = File.expand_path(File.dirname(__FILE__)) -$LOAD_PATH.unshift File.join(dir, 'lib') - require 'mocha' -require 'puppet' require 'rspec' - require 'puppet-strings' +require 'puppet-strings/yard' + +# Explicitly set up YARD once +PuppetStrings::Yard.setup! RSpec.configure do |config| - config.mock_with :mocha + config.mock_with :mocha + + config.before(:each) do + # Always clear the YARD registry before each example + YARD::Registry.clear + end end diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index 5a69594..a948d98 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -12,12 +12,11 @@ RSpec.configure do |c| # Configure all nodes in nodeset c.before :suite do - - hosts.each do |host| + hosts.each do |host| scp_to(host, Dir.glob('puppet-strings*.gem').first, 'puppet-strings.gem') on host, 'gem install puppet-strings.gem' - scp_to(host, Dir.glob('spec/unit/puppet/examples/test/pkg/username-test*.gz').first, 'test.tar.gz') + scp_to(host, Dir.glob('acceptance/fixtures/modules/test/pkg/username-test*.gz').first, 'test.tar.gz') on host, puppet('module', 'install', 'test.tar.gz') on host, 'gem install yard' diff --git a/spec/unit/puppet-strings/json_spec.rb b/spec/unit/puppet-strings/json_spec.rb new file mode 100644 index 0000000..4174f92 --- /dev/null +++ b/spec/unit/puppet-strings/json_spec.rb @@ -0,0 +1,132 @@ +require 'spec_helper' +require 'puppet-strings/json' +require 'tempfile' + +describe PuppetStrings::Json do + before :each do + # Populate the YARD registry with both Puppet and Ruby source + YARD::Parser::SourceParser.parse_string(<<-SOURCE, :puppet) +# A simple class. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +class klass(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { +} + +# A simple defined type. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +define dt(Integer $param1, $param2, String $param3 = hi) { +} + +# A simple function. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @return [Undef] Returns nothing. +function func(Integer $param1, $param2, String $param3 = hi) { +} +SOURCE + + YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby) +Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC +An example 3.x function. +@param [String] first The first parameter. +@param second The second parameter. +@return [Undef] Returns nothing. +DOC +) do |*args| +end + +# An example 4.x function. +Puppet::Functions.create_function(:func4x) do + # The first overload. + # @param param1 The first parameter. + # @param param2 The second parameter. + # @param param3 The third parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + param 'Integer', :param1 + param 'Any', :param2 + optional_param 'Array[String]', :param3 + end + + # The second overload. + # @param param The first parameter. + # @param block The block parameter. + # @return [String] Returns a string. + dispatch :other do + param 'Boolean', :param + block_param + end +end + +Puppet::Type.type(:database).provide :linux do + desc 'An example provider on Linux.' + confine kernel: 'Linux' + confine osfamily: 'RedHat' + defaultfor kernel: 'Linux' + has_feature :implements_some_feature + has_feature :some_other_feature + commands foo: /usr/bin/foo +end + +Puppet::Type.newtype(:database) do + desc 'An example database server resource type.' + feature :encryption, 'The provider supports encryption.', methods: [:encrypt] + ensurable do + desc 'What state the database should be in.' + defaultvalues + aliasvalue(:up, :present) + aliasvalue(:down, :absent) + defaultto :up + end + + newparam(:address) do + isnamevar + desc 'The database server name.' + end + + newparam(:encryption_key, required_features: :encryption) do + desc 'The encryption key to use.' + end + + newparam(:encrypt, :parent => Puppet::Parameter::Boolean) do + desc 'Whether or not to encrypt the database.' + defaultto false + end + + newproperty(:file) do + desc 'The database file to use.' + end + + newproperty(:log_level) do + desc 'The log level to use.' + newvalue(:debug) + newvalue(:warn) + newvalue(:error) + defaultto 'warn' + end +end +SOURCE + end + + let(:baseline_path) { File.join(File.dirname(__FILE__), '../../fixtures/unit/json/output.json') } + let(:baseline) { File.read(baseline_path) } + + describe 'rendering JSON to a file' do + it 'should output the expected JSON content' do + Tempfile.open('json') do |file| + PuppetStrings::Json.render(file.path) + expect(File.read(file.path)).to eq(baseline) + end + end + end + + describe 'rendering JSON to stdout' do + it 'should output the expected JSON content' do + expect{ PuppetStrings::Json.render(nil) }.to output(baseline).to_stdout + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb new file mode 100644 index 0000000..cc5b7c4 --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/puppet/class_handler_spec.rb @@ -0,0 +1,155 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Puppet::ClassHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :puppet) + YARD::Registry.all(:puppet_class) + } + + describe 'parsing source without a class definition' do + let(:source) { 'notice hi' } + + it 'no classes should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing source with a syntax error' do + let(:source) { 'class foo{' } + + it 'should log an error' do + expect{ subject }.to output(/\[error\]: Failed to parse \(stdin\): Syntax error at end of file/).to_stdout_from_any_process + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing a class with a missing docstring' do + let(:source) { 'class foo{}' } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing documentation for Puppet class 'foo' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a class with a docstring' do + let(:source) { <<-SOURCE +# A simple foo class. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should register a class object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Class) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Classes.instance) + expect(object.name).to eq(:foo) + expect(object.statement).not_to eq(nil) + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', 'hi']]) + expect(object.docstring).to eq('A simple foo class.') + expect(object.docstring.tags.size).to eq(4) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('First param.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('Second param.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('Third param.') + expect(tags[2].types).to eq(['String']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a class with a missing parameter' do + let(:source) { <<-SOURCE +# A simple foo class. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @param param4 missing! +class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param4' has no matching parameter at \(stdin\):6\./).to_stdout_from_any_process + end + end + + describe 'parsing a class with a missing @param tag' do + let(:source) { <<-SOURCE +# A simple foo class. +# @param param1 First param. +# @param param2 Second param. +class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @param tag for parameter 'param3' near \(stdin\):4\./).to_stdout_from_any_process + end + end + + describe 'parsing a class with a typed parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo class. +# @param [Boolean] param1 First param. +# @param param2 Second param. +# @param param3 Third param. +class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param1' should not contain a type specification near \(stdin\):5: ignoring in favor of parameter type information\./).to_stdout_from_any_process + end + end + + describe 'parsing a class with a untyped parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo class. +# @param param1 First param. +# @param [Boolean] param2 Second param. +# @param param3 Third param. +class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should respect the type that was documented' do + expect{ subject }.to output('').to_stdout_from_any_process + expect(subject.size).to eq(1) + tags = subject.first.tags(:param) + expect(tags.size).to eq(3) + expect(tags[1].types).to eq(['Boolean']) + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb new file mode 100644 index 0000000..633f8f0 --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/puppet/defined_type_handler_spec.rb @@ -0,0 +1,155 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Puppet::DefinedTypeHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :puppet) + YARD::Registry.all(:puppet_defined_type) + } + + describe 'parsing source without a defined type definition' do + let(:source) { 'notice hi' } + + it 'no defined types should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing source with a syntax error' do + let(:source) { 'define foo{' } + + it 'should log an error' do + expect{ subject }.to output(/\[error\]: Failed to parse \(stdin\): Syntax error at end of file/).to_stdout_from_any_process + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing a defined type with a missing docstring' do + let(:source) { 'define foo{}' } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing documentation for Puppet defined type 'foo' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a defined type with a docstring' do + let(:source) { <<-SOURCE +# A simple foo defined type. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +define foo(Integer $param1, $param2, String $param3 = hi) { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should register a defined type object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::DefinedType) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::DefinedTypes.instance) + expect(object.name).to eq(:foo) + expect(object.statement).not_to eq(nil) + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', 'hi']]) + expect(object.docstring).to eq('A simple foo defined type.') + expect(object.docstring.tags.size).to eq(4) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('First param.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('Second param.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('Third param.') + expect(tags[2].types).to eq(['String']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a defined type with a missing parameter' do + let(:source) { <<-SOURCE +# A simple foo defined type. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @param param4 missing! +define foo(Integer $param1, $param2, String $param3 = hi) { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param4' has no matching parameter at \(stdin\):6\./).to_stdout_from_any_process + end + end + + describe 'parsing a defined type with a missing @param tag' do + let(:source) { <<-SOURCE +# A simple foo defined type. +# @param param1 First param. +# @param param2 Second param. +define foo(Integer $param1, $param2, String $param3 = hi) { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @param tag for parameter 'param3' near \(stdin\):4\./).to_stdout_from_any_process + end + end + + describe 'parsing a defined type with a typed parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo defined type. +# @param [Boolean] param1 First param. +# @param param2 Second param. +# @param param3 Third param. +define foo(Integer $param1, $param2, String $param3 = hi) { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param1' should not contain a type specification near \(stdin\):5: ignoring in favor of parameter type information\./).to_stdout_from_any_process + end + end + + describe 'parsing a defined type with a untyped parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo defined type. +# @param param1 First param. +# @param [Boolean] param2 Second param. +# @param param3 Third param. +define foo(Integer $param1, $param2, String $param3 = hi) { + file { '/tmp/foo': + ensure => present + } +} +SOURCE + } + + it 'should respect the type that was documented' do + expect{ subject }.to output('').to_stdout_from_any_process + expect(subject.size).to eq(1) + tags = subject.first.tags(:param) + expect(tags.size).to eq(3) + expect(tags[1].types).to eq(['Boolean']) + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb new file mode 100644 index 0000000..81ae0be --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/puppet/function_handler_spec.rb @@ -0,0 +1,168 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Puppet::FunctionHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :puppet) + YARD::Registry.all(:puppet_function) + } + + describe 'parsing source without a function definition' do + let(:source) { 'notice hi' } + + it 'no functions should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing source with a syntax error' do + let(:source) { 'function foo{' } + + it 'should log an error' do + expect{ subject }.to output(/\[error\]: Failed to parse \(stdin\): Syntax error at end of file/).to_stdout_from_any_process + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing a function with a missing docstring' do + let(:source) { 'function foo{}' } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing documentation for Puppet function 'foo' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a docstring' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @return [Undef] Returns nothing. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' + undef +} +SOURCE + } + + it 'should register a function object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::PUPPET)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Integer $param1, Any $param2, String $param3 = hi)') + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', 'hi']]) + expect(object.docstring).to eq('A simple foo function.') + expect(object.docstring.tags.size).to eq(5) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('First param.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('Second param.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('Third param.') + expect(tags[2].types).to eq(['String']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a missing parameter' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @param param4 missing! +# @return [Undef] Returns nothing. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param4' has no matching parameter at \(stdin\):7\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a missing @param tag' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param param1 First param. +# @param param2 Second param. +# @return [Undef] Returns nothing. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @param tag for parameter 'param3' near \(stdin\):5\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a typed parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param [Boolean] param1 First param. +# @param param2 Second param. +# @param param3 Third param. +# @return [Undef] Returns nothing. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param1' should not contain a type specification near \(stdin\):6: ignoring in favor of parameter type information\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a untyped parameter that also has a @param tag type' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param param1 First param. +# @param [Boolean] param2 Second param. +# @param param3 Third param. +# @return [Undef] Returns nothing. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' +} +SOURCE + } + + it 'should respect the type that was documented' do + expect{ subject }.to output('').to_stdout_from_any_process + expect(subject.size).to eq(1) + tags = subject.first.tags(:param) + expect(tags.size).to eq(3) + expect(tags[1].types).to eq(['Boolean']) + end + end + + describe 'parsing a function with a missing @return tag' do + let(:source) { <<-SOURCE +# A simple foo function. +# @param param1 First param. +# @param param2 Second param. +# @param param3 Third param. +function foo(Integer $param1, $param2, String $param3 = hi) { + notice 'hello world' +} +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):5\./).to_stdout_from_any_process + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb new file mode 100644 index 0000000..d80e5a0 --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/ruby/function_handler_spec.rb @@ -0,0 +1,613 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Ruby::FunctionHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :ruby) + YARD::Registry.all(:puppet_function) + } + + describe 'parsing source without a function definition' do + let(:source) { 'puts "hi"' } + + it 'no functions should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing 3.x API functions' do + describe 'parsing a function with a missing docstring' do + let(:source) { <<-SOURCE +Puppet::Parser::Functions.newfunction(:foo) do |*args| +end +SOURCE + } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing documentation for Puppet function 'foo' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a doc parameter' do + let(:source) { <<-SOURCE +Puppet::Parser::Functions.newfunction(:foo, doc: <<-DOC +An example 3.x function. +@param [String] first The first parameter. +@param second The second parameter. +@return [Undef] Returns nothing. +DOC +) do |*args| +end +SOURCE + } + + it 'should register a function object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_3X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(String $first, Any $second)') + expect(object.parameters).to eq([['first', nil], ['second', nil]]) + expect(object.docstring).to eq('An example 3.x function.') + expect(object.docstring.tags.size).to eq(4) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(2) + expect(tags[0].name).to eq('first') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['String']) + expect(tags[1].name).to eq('second') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Any']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a missing @return tag' do + let(:source) { <<-SOURCE +Puppet::Parser::Functions.newfunction(:foo, doc: <<-DOC) do |*args| +An example 3.x function. +@param [String] first The first parameter. +@param second The second parameter. +DOC +end +SOURCE + } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):1/).to_stdout_from_any_process + end + end + end + + describe 'parsing 4.x API functions' do + describe 'parsing a function with a missing docstring' do + let(:source) { <<-SOURCE +Puppet::Functions.create_function(:foo) do +end +SOURCE + } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing documentation for Puppet function 'foo' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a simple docstring' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do +end +SOURCE + } + + it 'should register a function object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo()') + expect(object.parameters).to eq([]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags.size).to eq(1) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function without any dispatches' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param [Integer] param1 The first parameter. + # @param param2 The second parameter. + # @param [String] param3 The third parameter. + # @return [Undef] Returns nothing. + def foo(param1, param2, param3 = nil) + end +end +SOURCE + } + + it 'should register a function object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Integer $param1, Any $param2, Optional[String] $param3 = undef)') + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', 'undef']]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags.size).to eq(5) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('The third parameter.') + expect(tags[2].types).to eq(['Optional[String]']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a single dispatch' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param param1 The first parameter. + # @param param2 The second parameter. + # @param param3 The third parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + param 'Integer', :param1 + param 'Any', :param2 + optional_param 'Array[String]', :param3 + end + + def foo(param1, param2, param3 = nil) + end +end +SOURCE + } + + it 'should register a function object without any overload tags' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Integer $param1, Any $param2, Optional[Array[String]] $param3)') + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', nil]]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:overload).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(5) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('The third parameter.') + expect(tags[2].types).to eq(['Optional[Array[String]]']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with various dispatch parameters.' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param param1 The first parameter. + # @param param2 The second parameter. + # @param param3 The third parameter. + # @param param4 The fourth parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + param 'String', :param1 + required_param 'Integer', :param2 + optional_param 'Array', :param3 + repeated_param 'String', :param4 + end +end +SOURCE + } + + it 'should register a function object with the expected parameters' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(String $param1, Integer $param2, Optional[Array] $param3, String *$param4)') + expect(object.parameters).to eq([['param1', nil], ['param2', nil], ['param3', nil], ['*param4', nil]]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:overload).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(6) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(4) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['String']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Integer']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('The third parameter.') + expect(tags[2].types).to eq(['Optional[Array]']) + expect(tags[3].name).to eq('*param4') + expect(tags[3].text).to eq('The fourth parameter.') + expect(tags[3].types).to eq(['String']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with an optional repeated param.' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param param The first parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + optional_repeated_param 'String', :param + end +end +SOURCE + } + + it 'should register a function object with the expected parameters' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Optional[String] *$param)') + expect(object.parameters).to eq([['*param', nil]]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:overload).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(3) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(1) + expect(tags[0].name).to eq('*param') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['Optional[String]']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a block param with one parameter' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param a_block The block parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + block_param :a_block + end +end + SOURCE + } + + it 'should register a function object with the expected parameters' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Callable &$a_block)') + expect(object.parameters).to eq([['&a_block', nil]]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:overload).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(3) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(1) + expect(tags[0].name).to eq('&a_block') + expect(tags[0].text).to eq('The block parameter.') + expect(tags[0].types).to eq(['Callable']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a block param with two parameter' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param a_block The block parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + optional_block_param 'Callable[String]', :a_block + end +end + SOURCE + } + + it 'should register a function object with the expected parameters' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('foo(Optional[Callable[String]] &$a_block)') + expect(object.parameters).to eq([['&a_block', nil]]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:overload).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(3) + tags = object.docstring.tags(:param) + expect(tags.size).to eq(1) + expect(tags[0].name).to eq('&a_block') + expect(tags[0].text).to eq('The block parameter.') + expect(tags[0].types).to eq(['Optional[Callable[String]]']) + tags = object.docstring.tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + end + + describe 'parsing a function with a multiple dispatches' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # The first overload. + # @param param1 The first parameter. + # @param param2 The second parameter. + # @param param3 The third parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + param 'Integer', :param1 + param 'Any', :param2 + optional_param 'Array[String]', :param3 + end + + # The second overload. + # @param param The first parameter. + # @param block The block parameter. + # @return [String] Returns a string. + dispatch :other do + param 'Boolean', :param + block_param + end + + def foo(param1, param2, param3 = nil) + end + + def other(b) + 'lol' + end +end +SOURCE + } + + it 'should register a function object with overload tags' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Function) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Functions.instance(PuppetStrings::Yard::CodeObjects::Function::RUBY_4X)) + expect(object.name).to eq(:foo) + expect(object.signature).to eq('') + expect(object.parameters).to eq([]) + expect(object.docstring).to eq('An example 4.x function.') + expect(object.docstring.tags(:param).empty?).to be_truthy + expect(object.docstring.tags(:return).empty?).to be_truthy + expect(object.docstring.tags.size).to eq(3) + overloads = object.docstring.tags(:overload) + expect(overloads.size).to eq(2) + expect(overloads[0]).to be_a(PuppetStrings::Yard::Tags::OverloadTag) + expect(overloads[0].docstring).to eq('The first overload.') + expect(overloads[0].signature).to eq('foo(Integer $param1, Any $param2, Optional[Array[String]] $param3)') + expect(overloads[0].tags.size).to eq(4) + tags = overloads[0].tags(:param) + expect(tags.size).to eq(3) + expect(tags[0].name).to eq('param1') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['Integer']) + expect(tags[1].name).to eq('param2') + expect(tags[1].text).to eq('The second parameter.') + expect(tags[1].types).to eq(['Any']) + expect(tags[2].name).to eq('param3') + expect(tags[2].text).to eq('The third parameter.') + expect(tags[2].types).to eq(['Optional[Array[String]]']) + tags = overloads[0].tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns nothing.') + expect(tags[0].types).to eq(['Undef']) + expect(overloads[1]).to be_a(PuppetStrings::Yard::Tags::OverloadTag) + expect(overloads[1].docstring).to eq('The second overload.') + expect(overloads[1].signature).to eq('foo(Boolean $param, Callable &$block)') + expect(overloads[1].tags.size).to eq(3) + tags = overloads[1].tags(:param) + expect(tags.size).to eq(2) + expect(tags[0].name).to eq('param') + expect(tags[0].text).to eq('The first parameter.') + expect(tags[0].types).to eq(['Boolean']) + expect(tags[1].name).to eq('&block') + expect(tags[1].text).to eq('The block parameter.') + expect(tags[1].types).to eq(['Callable']) + tags = overloads[1].tags(:return) + expect(tags.size).to eq(1) + expect(tags[0].name).to be_nil + expect(tags[0].text).to eq('Returns a string.') + expect(tags[0].types).to eq(['String']) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + end + end + + describe 'parsing a function with a missing parameter' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param missing A missing parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + end +end +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'missing' has no matching parameter at \(stdin\):5/).to_stdout_from_any_process + end + end + + describe 'parsing a function with a missing @param tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @return [Undef] Returns nothing. + dispatch :foo do + param 'String', :param1 + end +end +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @param tag for parameter 'param1' near \(stdin\):5/).to_stdout_from_any_process + end + end + + describe 'parsing a function with a typed @param tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param [Integer] param1 The first parameter. + # @return [Undef] Returns nothing. + dispatch :foo do + param 'String', :param1 + end +end +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The @param tag for parameter 'param1' should not contain a type specification near \(stdin\):6: ignoring in favor of dispatch type information\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a typed @param tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +Puppet::Functions.create_function(:foo) do + # @param param1 The first parameter. + dispatch :foo do + param 'String', :param1 + end +end +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: Missing @return tag near \(stdin\):4/).to_stdout_from_any_process + end + end + + describe 'parsing a function with a root @param tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +# @param param Nope. +Puppet::Functions.create_function(:foo) do + # @return [Undef] + dispatch :foo do + end +end +SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The docstring for Puppet 4.x function 'foo' contains @param tags near \(stdin\):3: parameter documentation should be made on the dispatch call\./).to_stdout_from_any_process + end + end + + + describe 'parsing a function with a root @overload tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +# @overload foo +Puppet::Functions.create_function(:foo) do + # @return [Undef] + dispatch :foo do + end +end + SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The docstring for Puppet 4.x function 'foo' contains @overload tags near \(stdin\):3: overload tags are automatically generated from the dispatch calls\./).to_stdout_from_any_process + end + end + + describe 'parsing a function with a root @return tag' do + let(:source) { <<-SOURCE +# An example 4.x function. +# @return [Undef] foo +Puppet::Functions.create_function(:foo) do + # @return [Undef] + dispatch :foo do + end +end + SOURCE + } + + it 'should output a warning' do + expect{ subject }.to output(/\[warn\]: The docstring for Puppet 4.x function 'foo' contains @return tags near \(stdin\):3: return value documentation should be made on the dispatch call\./).to_stdout_from_any_process + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb new file mode 100644 index 0000000..9ae6b8e --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/ruby/provider_handler_spec.rb @@ -0,0 +1,62 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Ruby::ProviderHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :ruby) + YARD::Registry.all(:puppet_provider) + } + + describe 'parsing source without a provider definition' do + let(:source) { 'puts "hi"' } + + it 'no providers should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing a provider with a missing description' do + let(:source) { <<-SOURCE +Puppet::Type.type(:custom).provide :linux do +end +SOURCE + } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing a description for Puppet provider 'linux' \(resource type 'custom'\) at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a provider definition' do + let(:source) { <<-SOURCE +Puppet::Type.type(:custom).provide :linux do + desc 'An example provider on Linux.' + confine kernel: 'Linux' + confine osfamily: 'RedHat' + defaultfor kernel: 'Linux' + has_feature :implements_some_feature + has_feature :some_other_feature + commands foo: /usr/bin/foo +end +SOURCE + } + + it 'should register a provider object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Provider) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Providers.instance('custom')) + expect(object.name).to eq(:linux) + expect(object.type_name).to eq('custom') + expect(object.docstring).to eq('An example provider on Linux.') + expect(object.docstring.tags.size).to eq(1) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + expect(object.confines).to eq({ 'kernel' => 'Linux', 'osfamily' => 'RedHat'}) + expect(object.defaults).to eq({ 'kernel' => 'Linux'}) + expect(object.features).to eq(['implements_some_feature', 'some_other_feature']) + expect(object.commands).to eq({'foo' => '/usr/bin/foo'}) + end + end +end diff --git a/spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb b/spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb new file mode 100644 index 0000000..ec0894b --- /dev/null +++ b/spec/unit/puppet-strings/yard/handlers/ruby/type_handler_spec.rb @@ -0,0 +1,126 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Handlers::Ruby::TypeHandler do + subject { + YARD::Parser::SourceParser.parse_string(source, :ruby) + YARD::Registry.all(:puppet_type) + } + + describe 'parsing source without a type definition' do + let(:source) { 'puts "hi"' } + + it 'no types should be in the registry' do + expect(subject.empty?).to eq(true) + end + end + + describe 'parsing a type with a missing description' do + let(:source) { <<-SOURCE +Puppet::Type.newtype(:database) do +end +SOURCE + } + + it 'should log a warning' do + expect{ subject }.to output(/\[warn\]: Missing a description for Puppet resource type 'database' at \(stdin\):1\./).to_stdout_from_any_process + end + end + + describe 'parsing a type definition' do + let(:source) { <<-SOURCE +Puppet::Type.newtype(:database) do + desc 'An example database server resource type.' + feature :encryption, 'The provider supports encryption.', methods: [:encrypt] + ensurable do + desc 'What state the database should be in.' + defaultvalues + aliasvalue(:up, :present) + aliasvalue(:down, :absent) + defaultto :up + end + + newparam(:address) do + isnamevar + desc 'The database server name.' + end + + newparam(:encryption_key, required_features: :encryption) do + desc 'The encryption key to use.' + end + + newparam(:encrypt, :parent => Puppet::Parameter::Boolean) do + desc 'Whether or not to encrypt the database.' + defaultto false + end + + newproperty(:file) do + desc 'The database file to use.' + end + + newproperty(:log_level) do + desc 'The log level to use.' + newvalue(:debug) + newvalue(:warn) + newvalue(:error) + defaultto 'warn' + end +end +SOURCE + } + + it 'should register a type object' do + expect(subject.size).to eq(1) + object = subject.first + expect(object).to be_a(PuppetStrings::Yard::CodeObjects::Type) + expect(object.namespace).to eq(PuppetStrings::Yard::CodeObjects::Types.instance) + expect(object.name).to eq(:database) + expect(object.docstring).to eq('An example database server resource type.') + expect(object.docstring.tags.size).to eq(1) + tags = object.docstring.tags(:api) + expect(tags.size).to eq(1) + expect(tags[0].text).to eq('public') + expect(object.properties.size).to eq(3) + expect(object.properties[0].name).to eq('ensure') + expect(object.properties[0].docstring).to eq('What state the database should be in.') + expect(object.properties[0].isnamevar).to eq(false) + expect(object.properties[0].default).to eq('up') + expect(object.properties[0].values).to eq(%w(present absent up down)) + expect(object.properties[0].aliases).to eq({ 'down' => 'absent', 'up' => 'present' }) + expect(object.properties[1].name).to eq('file') + expect(object.properties[1].docstring).to eq('The database file to use.') + expect(object.properties[1].isnamevar).to eq(false) + expect(object.properties[1].default).to be_nil + expect(object.properties[1].values).to eq([]) + expect(object.properties[1].aliases).to eq({}) + expect(object.properties[2].name).to eq('log_level') + expect(object.properties[2].docstring).to eq('The log level to use.') + expect(object.properties[2].isnamevar).to eq(false) + expect(object.properties[2].default).to eq('warn') + expect(object.properties[2].values).to eq(%w(debug warn error)) + expect(object.properties[2].aliases).to eq({}) + expect(object.parameters.size).to eq(3) + expect(object.parameters[0].name).to eq('address') + expect(object.parameters[0].docstring).to eq('The database server name.') + expect(object.parameters[0].isnamevar).to eq(true) + expect(object.parameters[0].default).to be_nil + expect(object.parameters[0].values).to eq([]) + expect(object.parameters[0].aliases).to eq({}) + expect(object.parameters[1].name).to eq('encryption_key') + expect(object.parameters[1].docstring).to eq('The encryption key to use.') + expect(object.parameters[1].isnamevar).to eq(false) + expect(object.parameters[1].default).to be_nil + expect(object.parameters[1].values).to eq([]) + expect(object.parameters[1].aliases).to eq({}) + expect(object.parameters[2].name).to eq('encrypt') + expect(object.parameters[2].docstring).to eq('Whether or not to encrypt the database.') + expect(object.parameters[2].isnamevar).to eq(false) + expect(object.parameters[2].default).to eq('false') + expect(object.parameters[2].values).to eq(%w(true false yes no)) + expect(object.parameters[2].aliases).to eq({}) + expect(object.features.size).to eq(1) + expect(object.features[0].name).to eq('encryption') + expect(object.features[0].docstring).to eq('The provider supports encryption.') + end + end +end diff --git a/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb b/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb new file mode 100644 index 0000000..12ea9d5 --- /dev/null +++ b/spec/unit/puppet-strings/yard/parsers/puppet/parser_spec.rb @@ -0,0 +1,171 @@ +require 'spec_helper' +require 'puppet-strings/yard' + +describe PuppetStrings::Yard::Parsers::Puppet::Parser do + subject { PuppetStrings::Yard::Parsers::Puppet::Parser.new(source, file) } + let(:file) { 'test.pp' } + + describe 'initialization of the parser' do + let(:source) { 'notice hi' } + + it 'should store the original source' do + expect(subject.source).to eq(source) + end + + it 'should store the original file name' do + expect(subject.file).to eq(file) + end + + it 'should have no relevant statements' do + subject.parse + expect(subject.enumerator.empty?).to be_truthy + end + end + + describe 'parsing invalid Puppet source code' do + let(:source) { < present + } +} +SOURCE + } + + it 'should only return the class statement' do + subject.parse + expect(subject.enumerator.size).to eq(1) + statement = subject.enumerator.first + expect(statement).to be_a(PuppetStrings::Yard::Parsers::Puppet::ClassStatement) + expect(statement.source).to eq("class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar {\n file { '/tmp/foo':\n ensure => present\n }\n}") + expect(statement.file).to eq(file) + expect(statement.line).to eq(6) + expect(statement.docstring).to eq('A simple foo class.') + expect(statement.name).to eq('foo') + expect(statement.parent_class).to eq('foo::bar') + expect(statement.parameters.size).to eq(3) + expect(statement.parameters[0].name).to eq('param1') + expect(statement.parameters[0].type).to eq('Integer') + expect(statement.parameters[0].value).to be_nil + expect(statement.parameters[1].name).to eq('param2') + expect(statement.parameters[1].type).to be_nil + expect(statement.parameters[1].value).to be_nil + expect(statement.parameters[2].name).to eq('param3') + expect(statement.parameters[2].type).to eq('String') + expect(statement.parameters[2].value).to eq('hi') + end + end + + describe 'parsing nested class definitions' do + let(:source) { < present + } +} +SOURCE + } + + it 'should parse the defined type statement' do + subject.parse + expect(subject.enumerator.size).to eq(1) + statement = subject.enumerator.first + expect(statement).to be_a(PuppetStrings::Yard::Parsers::Puppet::DefinedTypeStatement) + expect(statement.name).to eq('foo') + expect(statement.source).to eq("define foo(Integer $param1, $param2, String $param3 = hi) {\n file { '/tmp/foo':\n ensure => present\n }\n}") + expect(statement.file).to eq(file) + expect(statement.line).to eq(6) + expect(statement.docstring).to eq('A simple foo defined type.') + expect(statement.parameters.size).to eq(3) + expect(statement.parameters[0].name).to eq('param1') + expect(statement.parameters[0].type).to eq('Integer') + expect(statement.parameters[0].value).to be_nil + expect(statement.parameters[1].name).to eq('param2') + expect(statement.parameters[1].type).to be_nil + expect(statement.parameters[1].value).to be_nil + expect(statement.parameters[2].name).to eq('param3') + expect(statement.parameters[2].type).to eq('String') + expect(statement.parameters[2].value).to eq('hi') + end + end + + describe 'parsing puppet functions' do + let(:source) { < Date: Wed, 14 Sep 2016 13:14:53 -0700 Subject: [PATCH 14/15] (maint) RuboCop fixes. This commit fixes a few RuboCop related failures. --- lib/puppet-strings/json.rb | 11 +++++------ lib/puppet-strings/yard.rb | 13 +++++++------ lib/puppet-strings/yard/code_objects/type.rb | 6 +++--- .../yard/handlers/ruby/provider_handler.rb | 7 ++++--- lib/puppet/face/strings.rb | 2 +- spec/spec_helper_acceptance.rb | 1 - 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/puppet-strings/json.rb b/lib/puppet-strings/json.rb index 32b8d52..d6d2e42 100644 --- a/lib/puppet-strings/json.rb +++ b/lib/puppet-strings/json.rb @@ -2,17 +2,16 @@ require 'json' # The module for JSON related functionality. module PuppetStrings::Json - # Renders the current YARD registry as JSON to the given file (or STDOUT if nil). # @param [String] file The path to the output file to render the registry to. If nil, output will be to STDOUT. # @return [void] def self.render(file = nil) document = { - puppet_classes: YARD::Registry.all(:puppet_class).sort_by! { |c| c.name }.map! { |c| c.to_hash }, - defined_types: YARD::Registry.all(:puppet_defined_type).sort_by! { |dt| dt.name }.map! { |dt| dt.to_hash }, - resource_types: YARD::Registry.all(:puppet_type).sort_by! { |t| t.name }.map! { |t| t.to_hash }, - providers: YARD::Registry.all(:puppet_provider).sort_by! { |p| p.name }.map! { |p| p.to_hash }, - puppet_functions: YARD::Registry.all(:puppet_function).sort_by! { |f| f.name }.map! { |f| f.to_hash }, + puppet_classes: YARD::Registry.all(:puppet_class).sort_by!(&:name).map!(&:to_hash), + defined_types: YARD::Registry.all(:puppet_defined_type).sort_by!(&:name).map!(&:to_hash), + resource_types: YARD::Registry.all(:puppet_type).sort_by!(&:name).map!(&:to_hash), + providers: YARD::Registry.all(:puppet_provider).sort_by!(&:name).map!(&:to_hash), + puppet_functions: YARD::Registry.all(:puppet_function).sort_by!(&:name).map!(&:to_hash), # TODO: Need Ruby documentation? } diff --git a/lib/puppet-strings/yard.rb b/lib/puppet-strings/yard.rb index 7e61cde..726b062 100644 --- a/lib/puppet-strings/yard.rb +++ b/lib/puppet-strings/yard.rb @@ -43,7 +43,7 @@ class YARD::CLI::Yardoc :puppet_defined_type, :puppet_type, :puppet_provider, - :puppet_function, + :puppet_function ) end end @@ -76,11 +76,12 @@ class YARD::CLI::Stats # Monkey patch output to accommodate our larger header widths @total += data if data.is_a?(Integer) && undoc @undocumented += undoc if undoc.is_a?(Integer) - if undoc - data = ('%5s (% 5d undocumented)' % [data, undoc]) - else - data = '%5s' % data - end + data = + if undoc + ('%5s (% 5d undocumented)' % [data, undoc]) + else + '%5s' % data + end log.puts('%-21s %s' % [name + ':', data]) end diff --git a/lib/puppet-strings/yard/code_objects/type.rb b/lib/puppet-strings/yard/code_objects/type.rb index 8e3185e..384ccf8 100644 --- a/lib/puppet-strings/yard/code_objects/type.rb +++ b/lib/puppet-strings/yard/code_objects/type.rb @@ -138,9 +138,9 @@ class PuppetStrings::Yard::CodeObjects::Type < PuppetStrings::Yard::CodeObjects: hash[:file] = file hash[:line] = line hash[:docstring] = PuppetStrings::Json.docstring_to_hash(docstring) - hash[:properties] = properties.map { |p| p.to_hash } if properties && !properties.empty? - hash[:parameters] = parameters.map { |p| p.to_hash } if parameters && !parameters.empty? - hash[:features] = features.map { |f| f.to_hash } if features && !features.empty? + hash[:properties] = properties.map(&:to_hash) if properties && !properties.empty? + hash[:parameters] = parameters.map(&:to_hash) if parameters && !parameters.empty? + hash[:features] = features.map(&:to_hash) if features && !features.empty? hash end end diff --git a/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb b/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb index 89929c9..5d4565e 100644 --- a/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb +++ b/lib/puppet-strings/yard/handlers/ruby/provider_handler.rb @@ -57,9 +57,10 @@ class PuppetStrings::Yard::Handlers::Ruby::ProviderHandler < PuppetStrings::Yard return nil elsif child.is_a?(YARD::Parser::Ruby::MethodCallNode) # Look for a call to a dispatch method with a block - next unless child.method_name && - (child.method_name.source == 'desc' || child.method_name.source == 'doc=') && - child.parameters(false).count == 1 + next unless + child.method_name && + (child.method_name.source == 'desc' || child.method_name.source == 'doc=') && + child.parameters(false).count == 1 docstring = node_as_string(child.parameters[0]) log.error "Failed to parse docstring for Puppet provider '#{object.name}' (resource type '#{object.type_name}') near #{child.file}:#{child.line}." and return nil unless docstring diff --git a/lib/puppet/face/strings.rb b/lib/puppet/face/strings.rb index ba441ed..06d4ce6 100644 --- a/lib/puppet/face/strings.rb +++ b/lib/puppet/face/strings.rb @@ -80,7 +80,7 @@ Puppet::Face.define(:strings, '0.0.1') do def check_required_features raise RuntimeError, "The 'yard' gem must be installed in order to use this face." unless Puppet.features.yard? raise RuntimeError, "The 'rgen' gem must be installed in order to use this face." unless Puppet.features.rgen? - raise RuntimeError, 'This face requires Ruby 1.9 or greater.' if RUBY_VERSION.match(/^1\.8/) + raise RuntimeError, 'This face requires Ruby 1.9 or greater.' if RUBY_VERSION =~ /^1\.8/ end # Builds the options to PuppetStrings.generate. diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb index a948d98..e64afc4 100644 --- a/spec/spec_helper_acceptance.rb +++ b/spec/spec_helper_acceptance.rb @@ -6,7 +6,6 @@ unless ENV['RS_PROVISION'] == 'no' end RSpec.configure do |c| - # Readable test descriptions c.formatter = :documentation From 01913fcfb0f12d8c209bd87a1b2cce8e075b9277 Mon Sep 17 00:00:00 2001 From: Peter Huene Date: Thu, 15 Sep 2016 15:45:44 -0700 Subject: [PATCH 15/15] (PDOC-63) Update README and JSON files. This commit updates the README and JSON documentation files to make them consistent with the refactoring work. --- JSON.md | 511 ++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 325 +++++++++++++++++++++++---------- json_dom.md | 121 ------------- 3 files changed, 739 insertions(+), 218 deletions(-) create mode 100644 JSON.md delete mode 100644 json_dom.md diff --git a/JSON.md b/JSON.md new file mode 100644 index 0000000..3029de9 --- /dev/null +++ b/JSON.md @@ -0,0 +1,511 @@ +Puppet Strings JSON Data +======================== + +Puppet Strings has two flags to the `generate` action that can be used to emit JSON data: + +* `--emit-json `: Emits the JSON data to the given file. +* `--emit-json-stdout`: Emits the JSON data to STDOUT. + +Document Schema +=============== + +At the top level, there are five arrays in the JSON document: + +| Document Key | Description | +| ---------------- | ----------------------------------------------------------------------------- | +| puppet_classes | The list of Puppet classes that were parsed. | +| defined_types | The list of defined types that were parsed. | +| resource_types | The list of resource types that were parsed. | +| providers | The list of resource providers that were parsed. | +| puppet_functions | The list of Puppet functions (3.x, 4.x and Puppet language) that were parsed. | + +Puppet Classes +-------------- + +Each entry in the `puppet_classes` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | ----------------------------------------------------- | +| name | The name of the Puppet class. | +| file | The file defining the Puppet class. | +| line | The line where the Puppet class is defined. | +| inherits | The name of the Puppet class the class inherits from. | +| docstring | The *DocString* object for the class (see below). | +| defaults | The map of parameter names to default values. | +| source | The Puppet source code for the class. | + +Defined Types +------------- + +Each entry in the `defined_types` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | -------------------------------------------------------- | +| name | The name of the defined type. | +| file | The file defining the defined type. | +| line | The line where the defined type is defined. | +| docstring | The *DocString* object for the defined type (see below). | +| defaults | The map of parameter names to default values. | +| source | The Puppet source code for the defined type. | + +Resource Types +-------------- + +Each entry in the `resource_types` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | --------------------------------------------------------- | +| name | The name of the resource type. | +| file | The file defining the resource type. | +| line | The line where the resource type is defined. | +| docstring | The *DocString* object for the resource type (see below). | +| properties | The list of properties for the resource type (see below). | +| parameters | The list of parameters for the resource type (see below). | +| features | The list of features for the resource type (see below). | + +Each entry in the `properties` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | ------------------------------------------------------- | +| name | The name of the property. | +| description | The description of the property. | +| values | The array of acceptable string values for the property. | +| aliases | The map of new values aliased to existing values. | +| isnamevar | True if the property is a namevar or false if not. | +| default | The default value for the property. | + +Each entry in the `parameters` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | -------------------------------------------------------- | +| name | The name of the parameter. | +| description | The description of the parameter. | +| values | The array of acceptable string values for the parameter. | +| aliases | The map of new values aliased to existing values. | +| isnamevar | True if the parameter is a namevar or false if not. | +| default | The default value for the parameter. | + +Each entry in the `features` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | ------------------------------- | +| name | The name of the feature. | +| description | The description of the feature. | + +Providers +--------- + +Each entry in the `providers` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | ---------------------------------------------------- | +| name | The name of the provider. | +| type_name | The name of the resource type of the provider. | +| file | The file defining the provider. | +| line | The line where the provider is defined. | +| docstring | The *DocString* object for the provider (see below). | +| confines | The string map of confines for the provider. | +| features | The list of features implemented by the provider. | +| defaults | The string map of "default for" for the provider. | +| commands | The string map of commands for the provider. | + +Puppet Functions +---------------- + +Each entry in the `puppet_functions` list is an object with the following attributes: + +| Attribute Key | Description | +| ------------- | ---------------------------------------------------- | +| name | The name of the function. | +| file | The file defining the provider. | +| line | The line where the provider is defined. | +| type | The function type (e.g. ruby3x, ruby4x, puppet). | +| signature | The Puppet signature of the function (no overloads). | +| docstring | The *DocString* object for the function (see below). | +| defaults | The map of parameter names to default values. | +| source | The source code for the function. | + +DocString Objects +----------------- + +For the above types, their docstrings are represented as an object with the following attributes: + +| Attribute Key | Description DocString | +| ------------- | --------------------------------------------------- | +| text | The textual part of the DocString. | +| tags | The array of tag objects, if any are present. | + +Each entry in the `tags` list is an object with the following properties: + +| Attribute Key | Description | +| ------------- | ------------------------------------------------------- | +| tag_name | The name of the tag (e.g. param, return, etc.). | +| text | The descriptive text of the tag. | +| types | The array of types associated with the tag. | +| name | The name associated with the tag (e.g. parameter name). | + +For Puppet 4.x functions with overloads, `overload` tags will contain three additional attributes: + +| Attribute Key | Description | +| ------------- | ----------------------------------------------- | +| signature | The Puppet signature of the overload. | +| docstring | The *DocString* object describing the overload. | +| defaults | The map of parameter names to default values. | + + +Example JSON Document +--------------------- + +An example JSON document describing a Puppet class, defined type, resource type, provider, and Puppet functions: + +```json +{ + "puppet_classes": [ + { + "name": "foo", + "file": "site.pp", + "line": 5, + "inherits": "foo::bar", + "docstring": { + "text": "A simple class.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "class foo(Integer $param1, $param2, String $param3 = hi) inherits foo::bar {\n}" + } + ], + "defined_types": [ + { + "name": "dt", + "file": "site.pp", + "line": 12, + "docstring": { + "text": "A simple defined type.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "define dt(Integer $param1, $param2, String $param3 = hi) {\n}" + } + ], + "resource_types": [ + { + "name": "database", + "file": "database.rb", + "line": 43, + "docstring": { + "text": "An example database server resource type." + }, + "properties": [ + { + "name": "ensure", + "description": "What state the database should be in.", + "values": [ + "present", + "absent", + "up", + "down" + ], + "aliases": { + "up": "present", + "down": "absent" + }, + "default": "up" + }, + { + "name": "file", + "description": "The database file to use." + }, + { + "name": "log_level", + "description": "The log level to use.", + "values": [ + "debug", + "warn", + "error" + ], + "default": "warn" + } + ], + "parameters": [ + { + "name": "address", + "description": "The database server name.", + "isnamevar": true + }, + { + "name": "encryption_key", + "description": "The encryption key to use." + }, + { + "name": "encrypt", + "description": "Whether or not to encrypt the database.", + "values": [ + "true", + "false", + "yes", + "no" + ], + "default": "false" + } + ], + "features": [ + { + "name": "encryption", + "description": "The provider supports encryption." + } + ] + } + ], + "providers": [ + { + "name": "linux", + "type_name": "database", + "file": "linux.rb", + "line": 33, + "docstring": { + "text": "An example provider on Linux." + }, + "confines": { + "kernel": "Linux", + "osfamily": "RedHat" + }, + "features": [ + "implements_some_feature", + "some_other_feature" + ], + "defaults": { + "kernel": "Linux" + }, + "commands": { + "foo": "/usr/bin/foo" + } + } + ], + "puppet_functions": [ + { + "name": "func", + "file": "site.pp", + "line": 20, + "type": "puppet", + "signature": "func(Integer $param1, Any $param2, String $param3 = hi)", + "docstring": { + "text": "A simple function.", + "tags": [ + { + "tag_name": "param", + "text": "First param.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "Second param.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "Third param.", + "types": [ + "String" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "defaults": { + "param3": "hi" + }, + "source": "function func(Integer $param1, $param2, String $param3 = hi) {\n}" + }, + { + "name": "func3x", + "file": "func3x.rb", + "line": 1, + "type": "ruby3x", + "signature": "func3x(String $first, Any $second)", + "docstring": { + "text": "An example 3.x function.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "String" + ], + "name": "first" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "second" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "source": "Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC\nAn example 3.x function.\n@param [String] first The first parameter.\n@param second The second parameter.\n@return [Undef] Returns nothing.\nDOC\n) do |*args|\nend" + }, + { + "name": "func4x", + "file": "func4x.rb", + "line": 11, + "type": "ruby4x", + "docstring": { + "text": "An example 4.x function.", + "tags": [ + { + "tag_name": "overload", + "signature": "func4x(Integer $param1, Any $param2, Optional[Array[String]] $param3)", + "docstring": { + "text": "The first overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Integer" + ], + "name": "param1" + }, + { + "tag_name": "param", + "text": "The second parameter.", + "types": [ + "Any" + ], + "name": "param2" + }, + { + "tag_name": "param", + "text": "The third parameter.", + "types": [ + "Optional[Array[String]]" + ], + "name": "param3" + }, + { + "tag_name": "return", + "text": "Returns nothing.", + "types": [ + "Undef" + ] + } + ] + }, + "name": "func4x" + }, + { + "tag_name": "overload", + "signature": "func4x(Boolean $param, Callable &$block)", + "docstring": { + "text": "The second overload.", + "tags": [ + { + "tag_name": "param", + "text": "The first parameter.", + "types": [ + "Boolean" + ], + "name": "param" + }, + { + "tag_name": "param", + "text": "The block parameter.", + "types": [ + "Callable" + ], + "name": "&block" + }, + { + "tag_name": "return", + "text": "Returns a string.", + "types": [ + "String" + ] + } + ] + }, + "name": "func4x" + } + ] + }, + "source": "Puppet::Functions.create_function(:func4x) do\n # The first overload.\n # @param param1 The first parameter.\n # @param param2 The second parameter.\n # @param param3 The third parameter.\n # @return [Undef] Returns nothing.\n dispatch :foo do\n param 'Integer', :param1\n param 'Any', :param2\n optional_param 'Array[String]', :param3\n end\n\n # The second overload.\n # @param param The first parameter.\n # @param block The block parameter.\n # @return [String] Returns a string.\n dispatch :other do\n param 'Boolean', :param\n block_param\n end\nend" + } + ] +} +``` + diff --git a/README.md b/README.md index 709fdcf..de38923 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,19 @@ Puppet Strings ============== [![Build Status](https://travis-ci.org/puppetlabs/puppet-strings.png?branch=master)](https://travis-ci.org/puppetlabs/puppet-strings) [![Gem Version](https://badge.fury.io/rb/puppet-strings.svg)](https://badge.fury.io/rb/puppet-strings) -A Puppet Face and plugin built on the [YARD Documentation Tool](http://yardoc.org/) and the Puppet 4 Parser. It is uses YARD and the Puppet Parser to generate HTML documentation about Puppet code and Puppet extensions written in Ruby. It will eventually replace the `puppet doc` command once feature parity has been achieved. +A Puppet command built on [YARD](http://yardoc.org/). -| | | -| -------------- |------------------------------------------------------------ | -| *Code* | [GitHub][repo] | -| *Issues* | [Puppet Labs' JIRA Tracker][JIRA] | -| *License* | [Apache 2.0][LICENSE] | -| *Change log* | [CHANGELOG.md][changelog] | -| *Contributing* | [CONTRIBUTING.md][contributing] and [COMMITTERS.md][committers]| +Puppet Strings generates HTML documentation for Puppet extensions written in Puppet and Ruby. + +This tool will eventually place the existing `puppet doc` command once feature parity has been achieved. + +| | | +| -------------- |---------------------------------------------------------------- | +| *Code* | [GitHub][repo] | +| *Issues* | [Puppet JIRA Tracker][JIRA] | +| *License* | [Apache 2.0][LICENSE] | +| *Change log* | [CHANGELOG.md][changelog] | +| *Contributing* | [CONTRIBUTING.md][contributing] and [COMMITTERS.md][committers] | [repo]: https://github.com/puppetlabs/puppet-strings [JIRA]: https://tickets.puppetlabs.com/browse/PDOC @@ -19,19 +23,19 @@ A Puppet Face and plugin built on the [YARD Documentation Tool](http://yardoc.or [contributing]: https://github.com/puppetlabs/puppet-strings/blob/master/CONTRIBUTING.md [committers]: https://github.com/puppetlabs/puppet-strings/blob/master/COMMITTERS.md -Installation +Requirements ------------ + In order to run strings you need to have the following software installed: * Ruby 1.9.3 or newer * Puppet 3.7 or newer - * The YARD RubyGem + * The `yard` Ruby gem Installing the YARD Gem ----------------------- -**Installing the YARD Gem with Puppet** -The easiest way to install the YARD gem is with Puppet itself. +The easiest way to install the `yard` gem is with Puppet itself: For Puppet 4.x: ``` @@ -43,9 +47,12 @@ For Puppet 3.x: $ puppet resource package yard provider=gem ``` -Installing Strings Itself +Installing Puppet Strings ------------------------- -Strings can be installed using the [puppet-strings RubyGem](https://rubygems.org/gems/puppet-strings). To ensure it is installed in right place, it is best to install it using Puppet. + +Strings can be installed using the [puppet-strings](https://rubygems.org/gems/puppet-strings) gem. + +To ensure it is installed in right place, it is best to install it using Puppet: For Puppet 4.x: ``` @@ -68,12 +75,12 @@ $ puppet strings ``` This processes `README` and all Puppet and Ruby source files under the `./manifests/`, `./functions/`, and `./lib/` -directories by default. +directories by default and creates HTML documentation under the `./doc/` directory. To document specific files: ``` -$ puppet strings first.pp second.pp ... +$ puppet strings generate first.pp second.pp ... ``` To document specific directories: @@ -82,21 +89,19 @@ To document specific directories: $ puppet strings 'modules/foo/lib/**/*.rb' 'modules/foo/manifests/**/*.pp' 'modules/foo/functions/**/*.pp' ... ``` -Strings can also emit the generated documentation as JSON: +Strings can emit JSON documenting the Puppet extensions: ``` -$ puppet strings generate manifest.pp --emit-json documentation.json +$ puppet strings generate --emit-json documentation.json ``` It can also print the JSON to stdout: ``` -$ puppet strings generate manifest.pp --emit-json-stdout +$ puppet strings generate --emit-json-stdout ``` -The schema for the JSON which Strings emits is [documented here](https://github.com/puppetlabs/puppet-strings/blob/master/json_dom.md). - -Processing is delegated to the `yard` tool so some options listed in `yard help doc` are available. However, Puppet Faces do not support passing arbitrary options through a face so these options must be specified in a `.yardopts` file. +The schema for the JSON output is [documented here](https://github.com/puppetlabs/puppet-strings/blob/master/JSON.md). In addition to generating a directory full of HTML, you can also serve up documentation for all your modules using the `server` action: @@ -104,87 +109,210 @@ In addition to generating a directory full of HTML, you can also serve up docume $ puppet strings server ``` -Writing Compatible Documentation --------------------------------- +YARD Options +------------ -Since the strings module is built around YARD, a few different comment formats can be used. YARD can work with RDoc, meaning it is backwards compatible with previously documented modules. Feel free to try out strings with RDoc, but we are planning to move to Markdown as the standard. You can configure which you would like YARD to use by adding a `.yardopts` file to the root of your module directory which specifies the desired format: +YARD options (see `yard help doc`) are supported in a `.yardopts` file in the same directory where `puppet strings` is run. -``` ---markup markdown -``` +Puppet Strings automatically sets the `markup` option to `markdown`, allowing your documentation strings to be in Markdown format. -While we have yet to decide exactly how documentation should work in the future, here are some very basic examples to get you started using the strings module. These are very much subject to change as we continue to work out a style guide. +Documenting Puppet Extensions +----------------------------- -### Functions -Here's an example of how you might document a 4x function: +### Puppet Classes / Defined Types -```ruby -# When given two numbers, returns the one that is larger. -# You could have a several line description here if you wanted, -# but I don't have much to say about this function. -# -# @example using two integers -# $bigger_int = max(int_one, int_two) -# -# @return [Integer] the larger of the two parameters -# -# @param num_a [Integer] the first number to be compared -# @param num_b [Integer] the second number to be compared -Puppet::Functions.create_function(:max) do - def max(num_a, num_b) - num_a >= num_b ? num_a : num_b - end -end -``` - -### Classes / Defined Types - -Here's an example of how you might document a class: +To document Puppet classes and defined types, use a YARD docstring before the class or defined type definition: ```puppet -# This class is meant to serve as an example of how one might -# want to document a manifest in a way that is compatible. -# with the strings module +# An example class. # -# @example when declaring the example class +# This is an example of how to document a Puppet class +# +# @example Declaring the class # include example # -# @param first_arg The first parameter for this class -# @param second_arg The second paramter for this class -class example ( - $first_arg = $example::params::first_arg, - $second_arg = $exampe::params::second_arg, -) { } +# @param first The first parameter for this class +# @param second The second paramter for this class +class example_class( + String $first = $example::params::first_arg, + Integer $second = $example::params::second_arg, +) inherits example::params { + # ... +} + +# An example defined type. +# +# This is an example of how to document a defined type. +# @param ports The array of port numbers to use. +define example_type( + Array[Integer] $ports = [] +) { + # ... +} ``` -### Types and Providers -Strings will automatically extract the `@doc` provider docstring and any `desc` parameter/property docstrings. +***Note: unlike Ruby, Puppet is a typed language; Puppet Strings will automatically use the parameter type information to +document the parameters. A warning will be emitted if you document parameter types.*** -Sometimes however, Puppet types use metaprogramming to create parameters and methods automatically. In those cases Strings will not be able to document them automatically (Strings doesn't execute the code that would generate those parameters), so you will need to provide hints on how to document your code. To document a parameter which is automatically created you must use the special directive `@!puppet.type.param` or `@!puppet.type.property` which may take types, the parameter or property name, and a description. +### Resource Types + +To document custom resource types and their parameters/properties, use the `desc` method or assign a value to the `doc` attribute: ```ruby -# @!puppet.type.param my_parameter This parameter needs to be explicitly -# documented as it is generated by mk_resource_methods -Puppet::Type.newtype(:minifile) do - - @doc = "Manages files, including their content, ownership, and permissions. - The provider can manage symbolic links." - - # This function does some metaprogramming on the new type. - mk_resource_methods - - newparam(:path) do - desc <<-'EOT' - The path to the file to manage. Must be fully qualified. - EOT - # ... do stuff here +Puppet::Type.newtype(:example) do + desc <<-DESC +An example resource type. +@example Using the type. + example { foo: + param => 'hi' + } +DESC + + newparam(:param) do + desc 'An example parameter.' + # ... end + + newproperty(:prop) do + desc 'An example property.' + #... + end + + # ... +end +``` + +Puppet Strings documents this way to preserve backwards compatibility with `puppet doc` and existing resource types. + +***Note: Puppet Strings does not evaluate your Ruby code, so only certain static expressions are supported.*** + +To document parameters and properties that are dynamically created, use the `#@!puppet.type.param` and `#@!puppet.type.property` +directives before the `newtype` call: + +```ruby +# @!puppet.type.param [value1, value2, value3] my_param Documentation for a dynamic parameter. +# @!puppet.type.property [foo, bar, baz] my_prop Documentation for a dynamic property. +Puppet::Type.newtype(:example) do + #... +end +``` + +### Providers + +To document providers, use the `desc` method or assign a value to the `doc` attribute: + +```ruby +Puppet::Type.type(:example).provide :platform do + desc 'An example provider.' + # ... end - - ``` +Puppet Strings documents this way to preserve backwards compatibility with `puppet doc` and existing resource types. + +***Note: Puppet Strings does not evaluate your Ruby code, so only certain static expressions are supported.*** + +### Functions + +Puppet Strings supports three different ways of defining a function in Puppet: with the Puppet 3.x API, Puppet 4.X API, +and in the Puppet language itself. + +## Puppet 3.x API + +To document a function in the Puppet 3.x API, use the `doc` option to `newfunction`: + +```ruby +Puppet::Parser::Functions.newfunction(:example, doc: <<-DOC +Documentation for an example 3.x function. +@param [String] param1 The first parameter. +@param [Integer] param2 The second parameter. +@return [Undef] +@example Calling the function. + example('hi', 10) +DOC +) do |*args| + #... +end +``` + +***Note: if parameter types are omitted, a default of the `Any` Puppet type will be used.*** + +## Puppet 4.x API + +To document a function in the Puppet 4.x API, use a YARD docstring before the `create_function` call and any `dispatch` +calls: + +```ruby +# An example 4.x function. +Puppet::Functions.create_function(:example) do + # @param first The first parameter. + # @param second The second parameter. + # @return [String] Returns a string. + # @example Calling the function + # example('hi', 10) + dispatch :example do + param 'String', :first + param 'Integer', :second + end + + # ... +end +``` + +***Note: Puppet Strings will automatically use the parameter type information from the `dispatch` block to document +the parameters. Only document your parameter types when the Puppet 4.x function contains no `dispatch` calls.*** + +If the Puppet 4.x function contains multiple `dispatch` calls, Puppet Strings will automatically create `overload` tags +to describe the function's overloads: + +```ruby +# An example 4.x function. +Puppet::Functions.create_function(:example) do + # Overload by string. + # @param first The first parameter. + # @return [String] Returns a string. + # @example Calling the function + # example('hi') + dispatch :example_string do + param 'String', :first + end + + # Overload by integer. + # @param first The first parameter. + # @return [Integer] Returns an integer. + # @example Calling the function + # example(10) + dispatch :example_integer do + param 'Integer', :first + end + + # ... +``` + +The resulting HTML for this example function will document both `example(String $first)` and `example(Integer $first)`. + +## Puppet Language + +To document Puppet functions written in the Puppet language, use a YARD docstring before the function definition: + +```puppet +# An example function written in Pupppet. +# @param name The name to say hello to. +# @return [String] Returns a string. +# @example Calling the function +# example('world') +function example(String $name) { + "hello $name" +} +``` + +***Note: Puppet Strings will automatically use the parameter type information from the function's parameters to document +the parameters.*** + +Additional Resources +-------------------- + Here are a few other good resources for getting started with documentation: * [Module README Template](https://docs.puppet.com/puppet/latest/reference/modules_documentation.html) @@ -239,29 +367,32 @@ This task aims to keep the `gh-pages` branch up to date with the current code an ***Please note this operation will be destructive if not used properly.*** Developing and Contributing ------ +--------------------------- -We love contributions from the community! If you'd like to contribute to the strings module, check out [CONTRIBUTING.md](https://github.com/puppetlabs/puppet-strings/blob/master/CONTRIBUTING.md) to get information on the contribution process. +We love contributions from the community! + +If you'd like to contribute to the strings module, check out [CONTRIBUTING.md](https://github.com/puppetlabs/puppet-strings/blob/master/CONTRIBUTING.md) to get information on the contribution process. Running Specs ------ +------------- -If you're going to be doing any development with puppet strings, it's essential that you can run the spec tests. You should simply have to do the following: +If you plan on developing features or fixing bugs in Puppet Strings, it is essential that you run specs before opening a pull request. + +To run specs, simply execute the `spec` rake task: $ bundle install --path .bundle/gems $ bundle exec rake spec Support ------ -Please log tickets and issues at our [JIRA tracker][JIRA]. A [mailing list](https://groups.google.com/forum/?fromgroups#!forum/puppet-users) is available for asking questions and getting help from others. In addition there is an active #puppet channel on Freenode. - -We use semantic version numbers for our releases, and recommend that users stay as up-to-date as possible by upgrading to patch releases and minor releases as they become available. - -Bugfixes and ongoing development will occur in minor releases for the current major version. Security fixes will be backported to a previous major version on a best-effort basis, until the previous major version is no longer maintained. - -Caveats ------- - - Documentation blocks must immediately precede the documented code with no whitespace. This is because the comment extractor possesses the elegance and intelligence of a bag of hammers. +Please log tickets and issues at our [JIRA tracker][JIRA]. A [mailing list](https://groups.google.com/forum/?fromgroups#!forum/puppet-users) +is available for asking questions and getting help from others. - - This project is very much a work in progress and may very well have undiscovered bugs and pitfalls. If you discover any of these, [please file a ticket](https://tickets.puppetlabs.com/browse/PDOC). +There is also an active #puppet channel on the Freenode IRC network. + +We use semantic version numbers for our releases, and recommend that users stay as up-to-date as possible by upgrading to +patch releases and minor releases as they become available. + +Bug fixes and ongoing development will occur in minor releases for the current major version. +Security fixes will be ported to a previous major version on a best-effort basis, until the previous major version is no longer maintained. diff --git a/json_dom.md b/json_dom.md deleted file mode 100644 index 3274307..0000000 --- a/json_dom.md +++ /dev/null @@ -1,121 +0,0 @@ -The Strings JSON Interchange Schema -=================================== - -Strings has two flags used to emit json. -* `--emit-json $FILE` Saves json to a file. -* `--emit-json-stdout` Prints json on stdout. - -Top Level Structure -------------------- - -The json outputted by strings is a single object which has 4 keys representing -the different types of Puppet code and extension functions Strings reads. The -value for each key is a list of json objects representing each puppet class, -function, etc. -Here is an example of the top level structure: - -```json -{ - -"defined_types": [...], - -"puppet_classes": [...], - -"puppet_functions": [...], - -"puppet_types": [...], - -"puppet_providers": [...] - -} -``` - -Defined Types -------------- - -Each defined type or puppet class object has the following properties and values: - -* `name`: A string representing the name of the object. -* `file`: The file the object came from. A string. -* `line`: The line in the file the object came from. A number. -* `docstring`: A string. The docstring describing the object. -* `examples`: A list of strings representing the content of the examples in the - docstring. -* `signatures`: A list of function signatures which may be supported by the - object. Each function signature is a json object whose keys are the - parameter names, and whose values are the types those parameters may take. - This is extracted from the code itself. -* `parameters`: An object whose keys are the parameter names and whose values - are the parameter's types or null if it has no types. This is extracted from - the docstring. - - -Puppet Functions ----------------- - -Both puppet 4x and 3x functions are represented as json objects kept in the -`puppet_functions` list. Puppet 4x functions have every property that 3x -functions have, as well as a few extras. - -Puppet 3x functions have: - -* `name`: A string representing the name of the -* `file`: The file the object came from. A string. -* `line`: The line in the file the object came from. A number. -* `docstring`: A string. The docstring describing our object. -* `function_api_version`: the number 3. -* `documented_params`: A object whose keys are the parameters which were -* documented and whose values are the types they may take, or null. -* `examples`: A list of strings representing the content of the examples in the - docstring. - -Puppet 4x functions have everything 3x functions do as well as: - -* The `function_api_version` is the number 4, not 3 (surprise!). -* `signatures`: A list of function signatures which may be supported by the - object. Each function signature is a json object whose keys are the parameter - names, and whose values are the types those parameters may take. This is - extracted from the code itself. - -Puppet Types ------------- - -Each puppet type object has the following properties and values: - -* `name`: A string representing the name of the object -* `file`: The file the object came from. A string. -* `line`: The line in the file the object came from. A number. -* `docstring`: A string. The docstring describing our object. -* `examples`: A list of strings representing the content of the examples in the - docstring. -* `parameters`: A list of objects with the following shape: - * `allowed_vales`: a list of strings representing the allowed values. - * `default`: a string or null. - * `docstring`: The docstring. - * `name`: the parameter name. -* `properties`: A list of objects with a shape very similar to parameters but - also including: - * `namevar`: A boolean. -* `features`: A list of objects representing possible features. They have the - following shape: - * `docstring`: The description of the feature. - * `methods`: null or a list of the available methods as strings. - * `name`: The feature's name. - -Puppet Providers ----------------- -Each puppet provider object has the following properties and values: - -* `name`: A string representing the name of the object -* `file`: The file the object came from. A string. -* `line`: The line in the file the object came from. A number. -* `docstring`: A string. The docstring describing the object. -* `examples`: A list of strings representing the content of the examples in the - docstring. -* `commands`: A list of the names of the commands available. -* `confines`: An object whose keys are the confine keys and whose values are - the confine values. -* `defaults`: Similar to above. -* `features`: A list of strings representing the features this provider - supports. -* `type_name`: The type this provider accompanies.