~ubuntu-branches/ubuntu/vivid/phabricator/vivid-proposed

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php

/**
 * Uses "CSS Lint" to detect checkstyle errors in css code.
 */
final class ArcanistCSSLintLinter extends ArcanistExternalLinter {

  public function getInfoName() {
    return 'CSSLint';
  }

  public function getInfoURI() {
    return 'http://csslint.net';
  }

  public function getInfoDescription() {
    return pht('Use `csslint` to detect issues with CSS source files.');
  }

  public function getLinterName() {
    return 'CSSLint';
  }

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

  public function getMandatoryFlags() {
    return array(
      '--format=lint-xml',
      '--quiet',
    );
  }

  public function getDefaultFlags() {
    return $this->getDeprecatedConfiguration('lint.csslint.options', array());
  }

  public function getDefaultBinary() {
    return $this->getDeprecatedConfiguration('lint.csslint.bin', 'csslint');
  }

  public function getVersion() {
    list($stdout) = execx('%C --version', $this->getExecutableCommand());

    $matches = array();
    if (preg_match('/^v(?P<version>\d+\.\d+\.\d+)$/', $stdout, $matches)) {
      return $matches['version'];
    } else {
      return false;
    }
  }

  public function getInstallInstructions() {
    return pht('Install CSSLint using `npm install -g csslint`.');
  }

  public function shouldExpectCommandErrors() {
    return true;
  }

  protected function parseLinterOutput($path, $err, $stdout, $stderr) {
    $report_dom = new DOMDocument();
    $ok = @$report_dom->loadXML($stdout);

    if (!$ok) {
      return false;
    }

    $files = $report_dom->getElementsByTagName('file');
    $messages = array();
    foreach ($files as $file) {
      foreach ($file->childNodes as $child) {
        if (!($child instanceof DOMElement)) {
          continue;
        }

        $data = $this->getData($path);
        $lines = explode("\n", $data);
        $name = $child->getAttribute('reason');
        $severity = ($child->getAttribute('severity') == 'warning')
          ? ArcanistLintSeverity::SEVERITY_WARNING
          : ArcanistLintSeverity::SEVERITY_ERROR;

        $message = new ArcanistLintMessage();
        $message->setPath($path);
        $message->setLine($child->getAttribute('line'));
        $message->setChar($child->getAttribute('char'));
        $message->setCode('CSSLint');
        $message->setDescription($child->getAttribute('reason'));
        $message->setSeverity($severity);

        if ($child->hasAttribute('line') && $child->getAttribute('line') > 0) {
          $line = $lines[$child->getAttribute('line') - 1];
          $text = substr($line, $child->getAttribute('char') - 1);
          $message->setOriginalText($text);
        }

        $messages[] = $message;
      }
    }

    return $messages;
  }

  protected function getLintCodeFromLinterConfigurationKey($code) {

    // NOTE: We can't figure out which rule generated each message, so we
    // can not customize severities. I opened a pull request to add this
    // ability; see:
    //
    // https://github.com/stubbornella/csslint/pull/409

    throw new Exception(
      pht(
        "CSSLint does not currently support custom severity levels, because ".
        "rules can't be identified from messages in output. ".
        "See Pull Request #409."));
  }

}