Skip to content

Commit

Permalink
Use tilde heredocs for readability
Browse files Browse the repository at this point in the history
This changes most heredocs to use the tilde syntax with variable
interpolation off. It indents the contents of the heredoc along with the
final symbol.

To maintain these changes, it enables `Layout/HeredocIndentation` and
`Layout/ClosingHeredocIndentation` in Rubocop.

The tilde syntax smartly strips the indentation, and allows for
different indention of the closing identifier:

```ruby
"test\n" == <<~'END'
    test
  END
```

This syntax was introduced in Ruby 2.3.0, so this will not pose
compatibility problems.

### Tests that should fail

Note that two tests couldn’t be updated to a more common heredoc format
to avoid failing.

It appears there is a problem with the way YARD parses parameters with
defaults with a heredoc ([YARD #779][]). There is a work-around for that
issue in `PuppetStrings::Yard::Handlers::Ruby::Base`, but it can’t work
in these cases because YARD doesn’t provide enough source to read the
whole heredoc content.

Given that these are tests of the Puppet 3 style functions, it’s
probably not worth pursuing this issue.

[YARD #779]: lsegal/yard#779
  • Loading branch information
danielparks committed Oct 4, 2022
1 parent e7c540f commit 2b01d3a
Show file tree
Hide file tree
Showing 26 changed files with 1,498 additions and 1,711 deletions.
4 changes: 2 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Layout/ArgumentAlignment:
Layout/BeginEndAlignment:
Enabled: false
Layout/ClosingHeredocIndentation:
Enabled: false
Enabled: true
Layout/EmptyComment:
Enabled: false
Layout/EmptyLineAfterGuardClause:
Expand All @@ -140,7 +140,7 @@ Layout/FirstArgumentIndentation:
Layout/HashAlignment:
Enabled: false
Layout/HeredocIndentation:
Enabled: false
Enabled: true
Layout/LeadingEmptyLines:
Enabled: false
Layout/SpaceAroundMethodCallOperator:
Expand Down
30 changes: 15 additions & 15 deletions spec/acceptance/generate_markdown_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,30 @@
sut_tmp_path
end

expected = <<-EOF
# Reference
expected = <<~'EOF'
# Reference
## Classes
* [`test`](#test): This class exists to serve as fixture data for testing the puppet strings face
## Classes
* [`test`](#test): This class exists to serve as fixture data for testing the puppet strings face
## Classes
## Classes
### test
### test
#### Examples
```puppet
class { "test": }
```
#### Examples
```puppet
class { "test": }
```
#### Parameters
#### Parameters
##### `package_name`
##### `package_name`
The name of the package
The name of the package
##### `service_name`
##### `service_name`
The name of the service
The name of the service
EOF

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
# @param [Integer] param2 param2 func1 documentation
# @return [Optional[String]]
Puppet::DataTypes.create_type('AcceptanceDataType') do
interface <<-PUPPET
interface <<~'PUPPET'
attributes => {
param1 => Variant[Numeric, String[1,2]],
param2 => { type => Optional[String[1]], value => "param2" }
},
functions => {
func1 => Callable[[String, Integer], Optional[String]]
}
PUPPET
PUPPET
end
4 changes: 2 additions & 2 deletions spec/fixtures/ruby/data_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
# @param [Integer] param2 param2 documentation
# @return [Optional[String]]
Puppet::DataTypes.create_type('UnitDataType') do
interface <<-PUPPET
interface <<~'PUPPET'
attributes => {
param1 => Variant[Numeric, String[1,2]],
param2 => { type => Optional[String[1]], value => "param2" }
},
functions => {
func1 => Callable[[String, Integer], Optional[String]]
}
PUPPET
PUPPET
end
19 changes: 9 additions & 10 deletions spec/fixtures/ruby/func3x.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# An example 3.x function
Puppet::Parser::Functions.newfunction(:func3x, doc: <<-DOC
Documentation for an example 3.x function.
@param param1 [String] The first parameter.
@param param2 [Integer] The second parameter.
@return [Undef]
@example Calling the function.
func3x('hi', 10)
DOC
) do |*args|
#...
Puppet::Parser::Functions.newfunction(:func3x, doc: <<~'DOC') do |*args|
Documentation for an example 3.x function.
@param param1 [String] The first parameter.
@param param2 [Integer] The second parameter.
@return [Undef]
@example Calling the function.
func3x('hi', 10)
DOC
# ...
end
26 changes: 13 additions & 13 deletions spec/fixtures/ruby/resource_api.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
Puppet::ResourceApi.register_type(
name: 'apt_key',
docs: <<-EOS,
@summary Example resource type using the new API.
@raise SomeError
This type provides Puppet with the capabilities to manage GPG keys needed
by apt to perform package validation. Apt has it's own GPG keyring that can
be manipulated through the `apt-key` command.
@example here's an example
apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
source => 'http://apt.puppetlabs.com/pubkey.gpg'
}
docs: <<~'EOS',
@summary Example resource type using the new API.
@raise SomeError
This type provides Puppet with the capabilities to manage GPG keys needed
by apt to perform package validation. Apt has it's own GPG keyring that can
be manipulated through the `apt-key` command.
@example here's an example
apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
source => 'http://apt.puppetlabs.com/pubkey.gpg'
}
**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute
path this type will autorequire that file.
**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute
path this type will autorequire that file.
EOS
attributes: {
ensure: {
Expand Down
22 changes: 11 additions & 11 deletions spec/fixtures/ruby/resource_type.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Puppet::Type.newtype(:database) do
desc <<-DESC
An example database server type.
@option opts :foo bar
@enum ensure :up Upstate
@enum ensure :down Downstate
@raise SomeError
@example here's an example
database { 'foo':
address => 'qux.baz.bar',
}
DESC
desc <<~'DESC'
An example database server type.
@option opts :foo bar
@enum ensure :up Upstate
@enum ensure :down Downstate
@raise SomeError
@example here's an example
database { 'foo':
address => 'qux.baz.bar',
}
DESC
feature :encryption, 'The provider supports encryption.', methods: [:encrypt]
ensurable do
desc 'What state the database should be in.'
Expand Down
170 changes: 85 additions & 85 deletions spec/unit/puppet-strings/describe_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,125 +15,125 @@
before :each do
# Populate the YARD registry with both Puppet and Ruby source

YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)
Puppet::Type.newtype(:database) do
desc 'An example database server resource type.'
end
YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby)
Puppet::Type.newtype(:database) do
desc 'An example database server resource type.'
end
SOURCE

YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)
Puppet::ResourceApi.register_type(
name: 'apt_key',
docs: <<-EOS,
@summary Example resource type using the new API.
@raise SomeError
This type provides Puppet with the capabilities to manage GPG keys needed
by apt to perform package validation. Apt has it's own GPG keyring that can
be manipulated through the `apt-key` command.
@example here's an example
apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
source => 'http://apt.puppetlabs.com/pubkey.gpg'
}
**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute
path this type will autorequire that file.
EOS
)
YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby)
Puppet::ResourceApi.register_type(
name: 'apt_key',
docs: <<~'EOS',
@summary Example resource type using the new API.
@raise SomeError
This type provides Puppet with the capabilities to manage GPG keys needed
by apt to perform package validation. Apt has it's own GPG keyring that can
be manipulated through the `apt-key` command.
@example here's an example
apt_key { '6F6B15509CF8E59E6E469F327F438280EF8D349F':
source => 'http://apt.puppetlabs.com/pubkey.gpg'
}
**Autorequires**:
If Puppet is given the location of a key file which looks like an absolute
path this type will autorequire that file.
EOS
)
SOURCE

YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)
Puppet::Type.type(:file).newproperty(:content) do
include Puppet::Util::Checksums
include Puppet::DataSync
YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby)
Puppet::Type.type(:file).newproperty(:content) do
include Puppet::Util::Checksums
include Puppet::DataSync
attr_reader :actual_content
attr_reader :actual_content
desc <<-'EOT'
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
EOT
end
desc <<~'EOT'
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
EOT
end
SOURCE

YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)
Puppet::Type.newtype(:file) do
include Puppet::Util::Checksums
include Puppet::Util::Backups
include Puppet::Util::SymbolicFileMode
YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby)
Puppet::Type.newtype(:file) do
include Puppet::Util::Checksums
include Puppet::Util::Backups
include Puppet::Util::SymbolicFileMode
@doc = "Manages files, including their content, ownership, and permissions.
@doc = "Manages files, including their content, ownership, and permissions.
The `file` type can manage normal files, directories, and symlinks; the
type should be specified in the `ensure` attribute."
The `file` type can manage normal files, directories, and symlinks; the
type should be specified in the `ensure` attribute."
newparam(:path) do
desc <<-'EOT'
The path to the file to manage. Must be fully qualified.
newparam(:path) do
desc <<~'EOT'
The path to the file to manage. Must be fully qualified.
On Windows, the path should include the drive letter and should use `/` as
the separator character (rather than `\\`).
EOT
isnamevar
end
On Windows, the path should include the drive letter and should use `/` as
the separator character (rather than `\`).
EOT
isnamevar
end
end
end
SOURCE

YARD::Parser::SourceParser.parse_string(<<-SOURCE, :ruby)
Puppet::Type.type(:file).newproperty(:source) do
include Puppet::Util::Checksums
include Puppet::DataSync
YARD::Parser::SourceParser.parse_string(<<~'SOURCE', :ruby)
Puppet::Type.type(:file).newproperty(:source) do
include Puppet::Util::Checksums
include Puppet::DataSync
attr_reader :actual_content
attr_reader :actual_content
desc <<-'EOT'
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
EOT
end
desc <<-'EOT'
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
EOT
end
SOURCE
end

describe 'rendering DESCRIBE to stdout' do
it 'outputs the expected describe content for the list of types' do
output = <<-DATA
These are the types known to puppet:
apt_key - This type provides Puppet with the capabiliti ...
database - An example database server resource type.
file - Manages files, including their content, owner ...
output = <<~'DATA'
These are the types known to puppet:
apt_key - This type provides Puppet with the capabiliti ...
database - An example database server resource type.
file - Manages files, including their content, owner ...
DATA
expect { described_class.render(nil, true) }.to output(output).to_stdout
end
it 'outputs the expected describe content for a type' do
output = <<-DATA
output = <<~'DATA'
file
====
Manages files, including their content, ownership, and permissions.
file
====
Manages files, including their content, ownership, and permissions.
The `file` type can manage normal files, directories, and symlinks; the
type should be specified in the `ensure` attribute.
The `file` type can manage normal files, directories, and symlinks; the
type should be specified in the `ensure` attribute.
Parameters
----------
Parameters
----------
- **content**
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
- **content**
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
- **path**
The path to the file to manage. Must be fully qualified.
- **path**
The path to the file to manage. Must be fully qualified.
On Windows, the path should include the drive letter and should use `/` as
the separator character (rather than `\\`).
On Windows, the path should include the drive letter and should use `/` as
the separator character (rather than `\`).
- **source**
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
- **source**
The desired contents of a file, as a string. This attribute is mutually
exclusive with `source` and `target`.
Providers
---------
Providers
---------
DATA
expect { described_class.render(['file']) }.to output(output).to_stdout
end
Expand Down
Loading

0 comments on commit 2b01d3a

Please sign in to comment.