Browse Source

FixCommand - simplify help

Dariusz Ruminski 3 years ago
parent
commit
5859e02e66

+ 1 - 1
doc/config.rst

@@ -26,7 +26,7 @@ The example below will add two rules to the default list of PSR2 set rules:
 
     $config = new PhpCsFixer\Config();
     return $config->setRules([
-            '@PSR2' => true,
+            '@PSR12' => true,
             'strict_param' => true,
             'array_syntax' => ['syntax' => 'short'],
         ])

+ 109 - 1
src/Console/Command/FixCommand.php

@@ -89,7 +89,115 @@ final class FixCommand extends Command
      */
     public function getHelp(): string
     {
-        return HelpCommand::getHelpCopy();
+        return <<<'EOF'
+The <info>%command.name%</info> command tries to fix as much coding standards
+problems as possible on a given file or files in a given directory and its subdirectories:
+
+    <info>$ php %command.full_name% /path/to/dir</info>
+    <info>$ php %command.full_name% /path/to/file</info>
+
+By default <comment>--path-mode</comment> is set to `override`, which means, that if you specify the path to a file or a directory via
+command arguments, then the paths provided to a `Finder` in config file will be ignored. You can use <comment>--path-mode=intersection</comment>
+to merge paths from the config file and from the argument:
+
+    <info>$ php %command.full_name% --path-mode=intersection /path/to/dir</info>
+
+The <comment>--format</comment> option for the output format. Supported formats are `txt` (default one), `json`, `xml`, `checkstyle`, `junit` and `gitlab`.
+
+NOTE: the output for the following formats are generated in accordance with XML schemas
+
+* `checkstyle` follows the common `"checkstyle" xml schema </doc/report-schema/checkstyle.xsd>`_
+* `junit` follows the `JUnit xml schema from Jenkins </doc/report-schema/junit-10.xsd>`_
+
+The <comment>--quiet</comment> Do not output any message.
+
+The <comment>--verbose</comment> option will show the applied rules. When using the `txt` format it will also display progress notifications.
+
+NOTE: if there is an error like "errors reported during linting after fixing", you can use this to be even more verbose for debugging purpose
+
+* `-v`: verbose
+* `-vv`: very verbose
+* `-vvv`: debug
+
+The <comment>--rules</comment> option limits the rules to apply to the
+project:
+
+    <info>$ php %command.full_name% /path/to/project --rules=@PSR12</info>
+
+By default the PSR12 rules are used.
+
+The <comment>--rules</comment> option lets you choose the exact rules to
+apply (the rule names must be separated by a comma):
+
+    <info>$ php %command.full_name% /path/to/dir --rules=line_ending,full_opening_tag,indentation_type</info>
+
+You can also exclude the rules you don't want by placing a dash in front of the rule name, if this is more convenient,
+using <comment>-name_of_fixer</comment>:
+
+    <info>$ php %command.full_name% /path/to/dir --rules=-full_opening_tag,-indentation_type</info>
+
+When using combinations of exact and exclude rules, applying exact rules along with above excluded results:
+
+    <info>$ php %command.full_name% /path/to/project --rules=@Symfony,-@PSR1,-blank_line_before_statement,strict_comparison</info>
+
+Complete configuration for rules can be supplied using a `json` formatted string.
+
+    <info>$ php %command.full_name% /path/to/project --rules='{"concat_space": {"spacing": "none"}}'</info>
+
+The <comment>--dry-run</comment> flag will run the fixer without making changes to your files.
+
+The <comment>--diff</comment> flag can be used to let the fixer output all the changes it makes.
+
+* <comment>null</comment>: no diff;
+* <comment>udiff</comment>: unified diff format.
+
+The <comment>--allow-risky</comment> option (pass `yes` or `no`) allows you to set whether risky rules may run. Default value is taken from config file.
+A rule is considered risky if it could change code behaviour. By default no risky rules are run.
+
+The <comment>--stop-on-violation</comment> flag stops the execution upon first file that needs to be fixed.
+
+The <comment>--show-progress</comment> option allows you to choose the way process progress is rendered:
+
+* <comment>none</comment>: disables progress output;
+* <comment>dots</comment>: multiline progress output with number of files and percentage on each line.
+
+If the option is not provided, it defaults to <comment>dots</comment> unless a config file that disables output is used, in which case it defaults to <comment>none</comment>. This option has no effect if the verbosity of the command is less than <comment>verbose</comment>.
+
+    <info>$ php %command.full_name% --verbose --show-progress=dots</info>
+
+The <comment>--dry-run</comment> option displays the files that need to be
+fixed but without actually modifying them:
+
+    <info>$ php %command.full_name% /path/to/code --dry-run</info>
+
+By using <command>--using-cache</command> option with `yes` or `no` you can set if the caching
+mechanism should be used.
+
+The command can also read from standard input, in which case it won't
+automatically fix anything:
+
+    <info>$ cat foo.php | php %command.full_name% --diff -</info>
+
+Finally, if you don't need BC kept on CLI level, you might use `PHP_CS_FIXER_FUTURE_MODE` to start using options that
+would be default in next MAJOR release and to forbid using deprecated configuration:
+
+    <info>$ PHP_CS_FIXER_FUTURE_MODE=1 php %command.full_name% -v --diff</info>
+
+Exit code
+---------
+
+Exit code of the fix command is built using following bit flags:
+
+*  0 - OK.
+*  1 - General error (or PHP minimal requirement not matched).
+*  4 - Some files have invalid syntax (only in dry-run mode).
+*  8 - Some files need fixing (only in dry-run mode).
+* 16 - Configuration error of the application.
+* 32 - Configuration error of a Fixer.
+* 64 - Exception raised within the application.
+
+EOF
+            ;
     }
 
     /**

+ 0 - 473
src/Console/Command/HelpCommand.php

@@ -14,22 +14,10 @@ declare(strict_types=1);
 
 namespace PhpCsFixer\Console\Command;
 
-use PhpCsFixer\AbstractFixer;
-use PhpCsFixer\Console\Application;
-use PhpCsFixer\Fixer\ConfigurableFixerInterface;
-use PhpCsFixer\Fixer\DeprecatedFixerInterface;
-use PhpCsFixer\Fixer\FixerInterface;
-use PhpCsFixer\FixerConfiguration\AliasedFixerOption;
 use PhpCsFixer\FixerConfiguration\AllowedValueSubset;
-use PhpCsFixer\FixerConfiguration\DeprecatedFixerOption;
 use PhpCsFixer\FixerConfiguration\FixerOptionInterface;
-use PhpCsFixer\FixerFactory;
 use PhpCsFixer\Preg;
-use PhpCsFixer\RuleSet\RuleSet;
-use PhpCsFixer\RuleSet\RuleSets;
-use PhpCsFixer\Utils;
 use Symfony\Component\Console\Command\HelpCommand as BaseHelpCommand;
-use Symfony\Component\Console\Formatter\OutputFormatter;
 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
 use Symfony\Component\Console\Input\InputInterface;
 use Symfony\Component\Console\Output\OutputInterface;
@@ -45,270 +33,6 @@ final class HelpCommand extends BaseHelpCommand
 {
     protected static $defaultName = 'help';
 
-    /**
-     * Returns help-copy suitable for console output.
-     */
-    public static function getHelpCopy(): string
-    {
-        $template =
-            <<<'EOF'
-The <info>%command.name%</info> command tries to fix as much coding standards
-problems as possible on a given file or files in a given directory and its subdirectories:
-
-    <info>$ php %command.full_name% /path/to/dir</info>
-    <info>$ php %command.full_name% /path/to/file</info>
-
-By default <comment>--path-mode</comment> is set to `override`, which means, that if you specify the path to a file or a directory via
-command arguments, then the paths provided to a `Finder` in config file will be ignored. You can use <comment>--path-mode=intersection</comment>
-to merge paths from the config file and from the argument:
-
-    <info>$ php %command.full_name% --path-mode=intersection /path/to/dir</info>
-
-The <comment>--format</comment> option for the output format. Supported formats are `txt` (default one), `json`, `xml`, `checkstyle`, `junit` and `gitlab`.
-
-NOTE: the output for the following formats are generated in accordance with XML schemas
-
-* `checkstyle` follows the common `"checkstyle" xml schema </doc/report-schema/checkstyle.xsd>`_
-* `junit` follows the `JUnit xml schema from Jenkins </doc/report-schema/junit-10.xsd>`_
-
-The <comment>--quiet</comment> Do not output any message.
-
-The <comment>--verbose</comment> option will show the applied rules. When using the `txt` format it will also display progress notifications.
-
-NOTE: if there is an error like "errors reported during linting after fixing", you can use this to be even more verbose for debugging purpose
-
-* `-v`: verbose
-* `-vv`: very verbose
-* `-vvv`: debug
-
-The <comment>--rules</comment> option limits the rules to apply to the
-project:
-
-    <info>$ php %command.full_name% /path/to/project --rules=@PSR12</info>
-
-By default the PSR12 rules are used.
-
-The <comment>--rules</comment> option lets you choose the exact rules to
-apply (the rule names must be separated by a comma):
-
-    <info>$ php %command.full_name% /path/to/dir --rules=line_ending,full_opening_tag,indentation_type</info>
-
-You can also exclude the rules you don't want by placing a dash in front of the rule name, if this is more convenient,
-using <comment>-name_of_fixer</comment>:
-
-    <info>$ php %command.full_name% /path/to/dir --rules=-full_opening_tag,-indentation_type</info>
-
-When using combinations of exact and exclude rules, applying exact rules along with above excluded results:
-
-    <info>$ php %command.full_name% /path/to/project --rules=@Symfony,-@PSR1,-blank_line_before_statement,strict_comparison</info>
-
-Complete configuration for rules can be supplied using a `json` formatted string.
-
-    <info>$ php %command.full_name% /path/to/project --rules='{"concat_space": {"spacing": "none"}}'</info>
-
-The <comment>--dry-run</comment> flag will run the fixer without making changes to your files.
-
-The <comment>--diff</comment> flag can be used to let the fixer output all the changes it makes.
-
-* <comment>null</comment>: no diff;
-* <comment>udiff</comment>: unified diff format.
-
-The <comment>--allow-risky</comment> option (pass `yes` or `no`) allows you to set whether risky rules may run. Default value is taken from config file.
-A rule is considered risky if it could change code behaviour. By default no risky rules are run.
-
-The <comment>--stop-on-violation</comment> flag stops the execution upon first file that needs to be fixed.
-
-The <comment>--show-progress</comment> option allows you to choose the way process progress is rendered:
-
-* <comment>none</comment>: disables progress output;
-* <comment>dots</comment>: multiline progress output with number of files and percentage on each line.
-
-If the option is not provided, it defaults to <comment>dots</comment> unless a config file that disables output is used, in which case it defaults to <comment>none</comment>. This option has no effect if the verbosity of the command is less than <comment>verbose</comment>.
-
-    <info>$ php %command.full_name% --verbose --show-progress=dots</info>
-
-The command can also read from standard input, in which case it won't
-automatically fix anything:
-
-    <info>$ cat foo.php | php %command.full_name% --diff -</info>
-
-Finally, if you don't need BC kept on CLI level, you might use `PHP_CS_FIXER_FUTURE_MODE` to start using options that
-would be default in next MAJOR release and to forbid using deprecated configuration:
-
-    <info>$ PHP_CS_FIXER_FUTURE_MODE=1 php %command.full_name% -v --diff</info>
-
-Rules
------
-
-Use the following command to quickly understand what a rule will do to your code:
-
-    <info>$ php php-cs-fixer.phar describe align_multiline_comment</info>
-
-To visualize all the rules that belong to a ruleset:
-
-    <info>$ php php-cs-fixer.phar describe @PSR12</info>
-
-Choose from the list of available rules:
-
-%%%FIXERS_DETAILS%%%
-
-The <comment>--dry-run</comment> option displays the files that need to be
-fixed but without actually modifying them:
-
-    <info>$ php %command.full_name% /path/to/code --dry-run</info>
-
-Config file
------------
-
-Instead of using command line options to customize the rule, you can save the
-project configuration in a <comment>.php-cs-fixer.dist.php</comment> file in the root directory of your project.
-The file must return an instance of `PhpCsFixer\ConfigInterface` (<url>%%%CONFIG_INTERFACE_URL%%%</url>)
-which lets you configure the rules, the files and directories that
-need to be analyzed. You may also create <comment>.php-cs-fixer.php</comment> file, which is
-the local configuration that will be used instead of the project configuration. It
-is a good practice to add that file into your <comment>.gitignore</comment> file.
-With the <comment>--config</comment> option you can specify the path to the
-<comment>.php-cs-fixer.php</comment> file.
-
-The example below will add two rules to the default list of PSR12 set rules:
-
-    <?php
-
-    $finder = PhpCsFixer\Finder::create()
-        ->exclude('somedir')
-        ->notPath('src/Symfony/Component/Translation/Tests/fixtures/resources.php')
-        ->in(__DIR__)
-    ;
-
-    $config = new Config();
-
-    return $config
-        ->setRules([
-            '@PSR12' => true,
-            'strict_param' => true,
-            'array_syntax' => ['syntax' => 'short'],
-        ])
-        ->setFinder($finder)
-    ;
-
-    ?>
-
-**NOTE**: `exclude` will work only for directories, so if you need to exclude file, try `notPath`.
-Both `exclude` and `notPath` methods accept only relative paths to the ones defined with the `in` method.
-
-See `Symfony\Finder` (<url>https://symfony.com/doc/current/components/finder.html</url>)
-online documentation for other `Finder` methods.
-
-You may also use an exclude list for the rules instead of the above shown include approach.
-The following example shows how to use all `Symfony` rules but the `full_opening_tag` rule.
-
-    <?php
-
-    $finder = PhpCsFixer\Finder::create()
-        ->exclude('somedir')
-        ->in(__DIR__)
-    ;
-
-    $config = new Config();
-
-    return $config
-        ->setRules([
-            '@Symfony' => true,
-            'full_opening_tag' => false,
-        ])
-        ->setFinder($finder)
-    ;
-
-    ?>
-
-You may want to use non-linux whitespaces in your project. Then you need to
-configure them in your config file.
-
-    <?php
-
-    $config = new Config();
-
-    return $config
-        ->setIndent("\t")
-        ->setLineEnding("\r\n")
-    ;
-
-    ?>
-
-By using `--using-cache` option with `yes` or `no` you can set if the caching
-mechanism should be used.
-
-Caching
--------
-
-The caching mechanism is enabled by default. This will speed up further runs by
-fixing only files that were modified since the last run. The tool will fix all
-files if the tool version has changed or the list of rules has changed.
-Cache is supported only for tool downloaded as phar file or installed via
-composer.
-
-Cache can be disabled via `--using-cache` option or config file:
-
-    <?php
-
-    $config = new Config();
-
-    return $config->setUsingCache(false);
-
-    ?>
-
-Cache file can be specified via `--cache-file` option or config file:
-
-    <?php
-
-    $config = new Config();
-
-    return $config->setCacheFile(__DIR__.'/.php-cs-fixer.cache');
-
-    ?>
-
-Using PHP CS Fixer on CI
-------------------------
-
-Require `friendsofphp/php-cs-fixer` as a `dev` dependency:
-
-    $ ./composer.phar require --dev friendsofphp/php-cs-fixer
-
-Then, add the following command to your CI:
-
-%%%CI_INTEGRATION%%%
-
-Where `$COMMIT_RANGE` is your range of commits, e.g. `$TRAVIS_COMMIT_RANGE` or `HEAD~..HEAD`.
-
-Exit code
----------
-
-Exit code of the fix command is built using following bit flags:
-
-*  0 - OK.
-*  1 - General error (or PHP minimal requirement not matched).
-*  4 - Some files have invalid syntax (only in dry-run mode).
-*  8 - Some files need fixing (only in dry-run mode).
-* 16 - Configuration error of the application.
-* 32 - Configuration error of a Fixer.
-* 64 - Exception raised within the application.
-
-EOF
-        ;
-
-        return strtr($template, [
-            '%%%CONFIG_INTERFACE_URL%%%' => sprintf(
-                'https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v%s/src/ConfigInterface.php',
-                self::getLatestReleaseVersionFromChangeLog()
-            ),
-            '%%%CI_INTEGRATION%%%' => implode("\n", array_map(
-                static function (string $line) { return '    $ '.$line; },
-                \array_slice(file(__DIR__.'/../../../ci-integration.sh', FILE_IGNORE_NEW_LINES), 3)
-            )),
-            '%%%FIXERS_DETAILS%%%' => self::getFixersHelp(),
-        ]);
-    }
-
     /**
      * @param mixed $value
      */
@@ -355,50 +79,6 @@ EOF
         return $allowed;
     }
 
-    /**
-     * @throws \RuntimeException when failing to parse the change log file
-     */
-    public static function getLatestReleaseVersionFromChangeLog(): string
-    {
-        static $version = null;
-
-        if (null !== $version) {
-            return $version;
-        }
-
-        $changelogFile = self::getChangeLogFile();
-        if (null === $changelogFile) {
-            $version = Application::VERSION;
-
-            return $version;
-        }
-
-        $changelog = @file_get_contents($changelogFile);
-        if (false === $changelog) {
-            $error = error_get_last();
-
-            throw new \RuntimeException(sprintf(
-                'Failed to read content of the changelog file "%s".%s',
-                $changelogFile,
-                $error ? ' '.$error['message'] : ''
-            ));
-        }
-
-        for ($i = Application::getMajorVersion(); $i > 0; --$i) {
-            if (1 === Preg::match('/Changelog for v('.$i.'.\d+.\d+)/', $changelog, $matches)) {
-                $version = $matches[1];
-
-                break;
-            }
-        }
-
-        if (null === $version) {
-            throw new \RuntimeException(sprintf('Failed to parse changelog data of "%s".', $changelogFile));
-        }
-
-        return $version;
-    }
-
     /**
      * {@inheritdoc}
      */
@@ -407,159 +87,6 @@ EOF
         $output->getFormatter()->setStyle('url', new OutputFormatterStyle('blue'));
     }
 
-    private static function getChangeLogFile(): ?string
-    {
-        $changelogFile = __DIR__.'/../../../CHANGELOG.md';
-
-        return is_file($changelogFile) ? $changelogFile : null;
-    }
-
-    private static function getFixersHelp(): string
-    {
-        $help = '';
-        $fixerFactory = new FixerFactory();
-        /** @var AbstractFixer[] $fixers */
-        $fixers = $fixerFactory->registerBuiltInFixers()->getFixers();
-
-        // sort fixers by name
-        usort(
-            $fixers,
-            static function (FixerInterface $a, FixerInterface $b) {
-                return strcmp($a->getName(), $b->getName());
-            }
-        );
-
-        $ruleSets = [];
-        foreach (RuleSets::getSetDefinitionNames() as $setName) {
-            $ruleSets[$setName] = new RuleSet([$setName => true]);
-        }
-
-        $getSetsWithRule = static function (string $rule) use ($ruleSets) {
-            $sets = [];
-
-            foreach ($ruleSets as $setName => $ruleSet) {
-                if ($ruleSet->hasRule($rule)) {
-                    $sets[] = $setName;
-                }
-            }
-
-            return $sets;
-        };
-
-        $count = \count($fixers) - 1;
-        foreach ($fixers as $i => $fixer) {
-            $sets = $getSetsWithRule($fixer->getName());
-            $description = $fixer->getDefinition()->getSummary();
-
-            if ($fixer instanceof DeprecatedFixerInterface) {
-                $successors = $fixer->getSuccessorsNames();
-                $message = [] === $successors
-                    ? 'will be removed on next major version'
-                    : sprintf('use %s instead', Utils::naturalLanguageJoinWithBackticks($successors));
-                $description .= sprintf(' DEPRECATED: %s.', $message);
-            }
-
-            $description = implode("\n   | ", self::wordwrap(
-                Preg::replace('/(`.+?`)/', '<info>$1</info>', $description),
-                72
-            ));
-
-            if (!empty($sets)) {
-                $help .= sprintf(" * <comment>%s</comment> [%s]\n   | %s\n", $fixer->getName(), implode(', ', $sets), $description);
-            } else {
-                $help .= sprintf(" * <comment>%s</comment>\n   | %s\n", $fixer->getName(), $description);
-            }
-
-            if ($fixer->isRisky()) {
-                $help .= sprintf(
-                    "   | *Risky rule: %s.*\n",
-                    Preg::replace(
-                        '/(`.+?`)/',
-                        '<info>$1</info>',
-                        lcfirst(Preg::replace('/\.$/', '', $fixer->getDefinition()->getRiskyDescription()))
-                    )
-                );
-            }
-
-            if ($fixer instanceof ConfigurableFixerInterface) {
-                $configurationDefinition = $fixer->getConfigurationDefinition();
-                $configurationDefinitionOptions = $configurationDefinition->getOptions();
-                if (\count($configurationDefinitionOptions)) {
-                    $help .= "   |\n   | Configuration options:\n";
-
-                    usort(
-                        $configurationDefinitionOptions,
-                        static function (FixerOptionInterface $optionA, FixerOptionInterface $optionB) {
-                            return strcmp($optionA->getName(), $optionB->getName());
-                        }
-                    );
-
-                    foreach ($configurationDefinitionOptions as $option) {
-                        $line = '<info>'.OutputFormatter::escape($option->getName()).'</info>';
-
-                        $allowed = self::getDisplayableAllowedValues($option);
-                        if (null !== $allowed) {
-                            foreach ($allowed as &$value) {
-                                if ($value instanceof AllowedValueSubset) {
-                                    $value = 'a subset of <comment>'.self::toString($value->getAllowedValues()).'</comment>';
-                                } else {
-                                    $value = '<comment>'.self::toString($value).'</comment>';
-                                }
-                            }
-                        } else {
-                            $allowed = array_map(
-                                static function (string $type) {
-                                    return '<comment>'.$type.'</comment>';
-                                },
-                                $option->getAllowedTypes()
-                            );
-                        }
-
-                        if (null !== $allowed) {
-                            $line .= ' ('.implode(', ', $allowed).')';
-                        }
-
-                        $line .= ': '.Preg::replace(
-                            '/(`.+?`)/',
-                            '<info>$1</info>',
-                            lcfirst(Preg::replace('/\.$/', '', OutputFormatter::escape($option->getDescription())))
-                        ).'; ';
-                        if ($option->hasDefault()) {
-                            $line .= 'defaults to <comment>'.self::toString($option->getDefault()).'</comment>';
-                        } else {
-                            $line .= 'required';
-                        }
-
-                        if ($option instanceof DeprecatedFixerOption) {
-                            $line .= '. DEPRECATED: '.Preg::replace(
-                                '/(`.+?`)/',
-                                '<info>$1</info>',
-                                lcfirst(Preg::replace('/\.$/', '', OutputFormatter::escape($option->getDeprecationMessage())))
-                            );
-                        }
-
-                        if ($option instanceof AliasedFixerOption) {
-                            $line .= '; DEPRECATED alias: <comment>'.$option->getAlias().'</comment>';
-                        }
-
-                        foreach (self::wordwrap($line, 72) as $index => $line) {
-                            $help .= (0 === $index ? '   | - ' : '   |   ').$line."\n";
-                        }
-                    }
-                }
-            } elseif ($fixer instanceof ConfigurableFixerInterface) {
-                $help .= "   | *Configurable rule.*\n";
-            }
-
-            if ($count !== $i) {
-                $help .= "\n";
-            }
-        }
-
-        // prevent "\</foo>" from being rendered as an escaped literal style tag
-        return Preg::replace('#\\\\(</.*?>)#', '<<$1', $help);
-    }
-
     /**
      * Wraps a string to the given number of characters, ignoring style tags.
      *

+ 0 - 15
tests/Console/Command/HelpCommandTest.php

@@ -14,7 +14,6 @@ declare(strict_types=1);
 
 namespace PhpCsFixer\Tests\Console\Command;
 
-use PhpCsFixer\Console\Application;
 use PhpCsFixer\Console\Command\HelpCommand;
 use PhpCsFixer\FixerConfiguration\FixerOption;
 use PhpCsFixer\FixerConfiguration\FixerOptionInterface;
@@ -69,18 +68,4 @@ final class HelpCommandTest extends TestCase
         yield [[0, 3, 9], new FixerOption('foo', 'bar', false, null, ['int'], [0, 3, 9, static function (): void {}])];
         yield [null, new FixerOption('foo', 'bar')];
     }
-
-    public function testGetLatestReleaseVersionFromChangeLog(): void
-    {
-        $helpVersion = HelpCommand::getLatestReleaseVersionFromChangeLog();
-        $appVersion = Application::VERSION;
-        static::assertTrue(
-            version_compare($helpVersion, $appVersion, '<='),
-            sprintf(
-                'Expected version from change log "%s" <= as application version "%s".',
-                $helpVersion,
-                $appVersion
-            )
-        );
-    }
 }