Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ktlint arcanist plugin? #1073

Closed
martijnthe opened this issue Jan 29, 2021 · 3 comments
Closed

ktlint arcanist plugin? #1073

martijnthe opened this issue Jan 29, 2021 · 3 comments

Comments

@martijnthe
Copy link

In your blog post , you mention having a plugin for arcanist. Supposedly it’s only 65 lines of php code. Nonetheless it would be nice to not have to reinvent the wheel. It would be awesome if you could open-source the plug-in!

thanks 🙏

See also pinterest/arcanist-linters#47 (comment)

@shashachu
Copy link
Contributor

Sure - will work on that. Thanks for the nudge.

@kenyee
Copy link

kenyee commented Jul 28, 2022

+1...please share 😄

@shashachu
Copy link
Contributor

Here is approximately what we use. It worked well for us when we first switched to Kotlin and could gradually run ktlint on the codebase as more Kotlin appeared, as Arcanist lint only runs on changed files.

<?php
final class ArcanistKotlinLinter extends ArcanistLinter
{
    public function getInfoName()
    {
        return "Kotlin Linter";
    }

    public function getInfoDescription() 
    {
        return "Runs ktlint command line on Kotlin files.";
    }

    public function getLinterConfigurationName()
    {
        return 'ktlint';
    }

    public function getLinterName()
    {
        return 'Kotlin Linter';
    }

    protected function shouldLintDirectories()
    {
        return true;
    }

    public function lintPath($path)
    {
        $root = $this->getEngine()->getWorkingCopy()->getProjectRoot();

        $cwd = getcwd();
        chdir($root);

        $jarPath = "./path/to/your/custom/rules.jar";

        if (!file_exists($jarPath)) {
            throw new ArcanistUsageException("Can't find custom rules jar.");
        }

        $filePath = Filesystem::resolvePath($path, $root);
        $orig = file_get_contents($filePath);

        // Run with -F so that any violations that can be auto-corrected are.
        // Also link in our custom ruleset
        $cmd = "path/to/ktlint --experimental -F -R " . $jarPath . " %s";
        // Run the command line ktlint on the path
        list ($err, $stdout, $stderr) = exec_manual($cmd, $path);

        // Split the output by line
        $output_lines = explode("\n", $stdout);

        $formatted = file_get_contents($filePath);

        if ($orig != $formatted) {
            $message = id(new ArcanistLintMessage())
                  ->setPath($path)
                  ->setLine(1)
                  ->setChar(1)
                  ->setGranularity(ArcanistLinter::GRANULARITY_FILE)
                  ->setCode('KFMT')
                  ->setSeverity(ArcanistLintSeverity::SEVERITY_AUTOFIX)
                  ->setName('Code style violation')
                  ->setDescription("'$path' has code style errors.")
                  ->setOriginalText($orig)
                  ->setReplacementText($formatted);
            $this->addLintMessage($message);
        }

        file_put_contents($filePath, $orig);

        if (sizeof($output_lines) > 0) {
            $pattern = "/(^[\S]+.kt):([\d]+):([\d]+):\S* (.+$)/";

            foreach ($output_lines as $line) {
                preg_match($pattern, $line, $matches);
                if (!empty($matches)) {
                    $desc = $matches[4];
                    // The autofixable errors have already been autocorrected, so only show the true errors here.
                    if (!$this->canAutofix($desc)) {
                        $message = new ArcanistLintMessage();
                        $message->setName("Kotlin Lint Error");
                        $message->setPath($path);
                        $message->setDescription($matches[4]);
                        $message->setLine(intval($matches[2]));
                        $message->setSeverity(ArcanistLintSeverity::SEVERITY_ERROR);

                        $this->addLintMessage($message);
                    }
                }
            }
        }

        chdir($cwd);
    }

    private function canAutofix($text) {
        return strpos($text, "(cannot be auto-corrected)") === false;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants