~ubuntu-branches/ubuntu/wily/phabricator/wily

« back to all changes in this revision

Viewing changes to src/lint/linter/ArcanistBaseXHPASTLinter.php

  • Committer: Package Import Robot
  • Author(s): Richard Sellam
  • Date: 2014-11-01 23:20:06 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: package-import@ubuntu.com-20141101232006-mvlnp0cil67tsboe
Tags: upstream-0~git20141101/arcanist
Import upstream version 0~git20141101, component arcanist

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
 
 
3
/**
 
4
 * @task sharing Sharing Parse Trees
 
5
 */
 
6
abstract class ArcanistBaseXHPASTLinter extends ArcanistFutureLinter {
 
7
 
 
8
  private $futures = array();
 
9
  private $trees = array();
 
10
  private $exceptions = array();
 
11
 
 
12
  final public function getCacheVersion() {
 
13
    $parts = array();
 
14
 
 
15
    $parts[] = $this->getVersion();
 
16
 
 
17
    $path = xhpast_get_binary_path();
 
18
    if (Filesystem::pathExists($path)) {
 
19
      $parts[] = md5_file($path);
 
20
    }
 
21
 
 
22
    return implode('-', $parts);
 
23
  }
 
24
 
 
25
  final protected function raiseLintAtToken(
 
26
    XHPASTToken $token,
 
27
    $code,
 
28
    $desc,
 
29
    $replace = null) {
 
30
    return $this->raiseLintAtOffset(
 
31
      $token->getOffset(),
 
32
      $code,
 
33
      $desc,
 
34
      $token->getValue(),
 
35
      $replace);
 
36
  }
 
37
 
 
38
  final protected function raiseLintAtNode(
 
39
    XHPASTNode $node,
 
40
    $code,
 
41
    $desc,
 
42
    $replace = null) {
 
43
    return $this->raiseLintAtOffset(
 
44
      $node->getOffset(),
 
45
      $code,
 
46
      $desc,
 
47
      $node->getConcreteString(),
 
48
      $replace);
 
49
  }
 
50
 
 
51
  final protected function buildFutures(array $paths) {
 
52
    return $this->getXHPASTLinter()->buildSharedFutures($paths);
 
53
  }
 
54
 
 
55
 
 
56
/* -(  Sharing Parse Trees  )------------------------------------------------ */
 
57
 
 
58
  /**
 
59
   * Get the linter object which is responsible for building parse trees.
 
60
   *
 
61
   * When the engine specifies that several XHPAST linters should execute,
 
62
   * we designate one of them as the one which will actually build parse trees.
 
63
   * The other linters share trees, so they don't have to recompute them.
 
64
   *
 
65
   * Roughly, the first linter to execute elects itself as the builder.
 
66
   * Subsequent linters request builds and retrieve results from it.
 
67
   *
 
68
   * @return ArcanistBaseXHPASTLinter Responsible linter.
 
69
   * @task sharing
 
70
   */
 
71
  final protected function getXHPASTLinter() {
 
72
    $resource_key = 'xhpast.linter';
 
73
 
 
74
    // If we're the first linter to run, share ourselves. Otherwise, grab the
 
75
    // previously shared linter.
 
76
 
 
77
    $engine = $this->getEngine();
 
78
    $linter = $engine->getLinterResource($resource_key);
 
79
    if (!$linter) {
 
80
      $linter = $this;
 
81
      $engine->setLinterResource($resource_key, $linter);
 
82
    }
 
83
 
 
84
    $base_class = __CLASS__;
 
85
    if (!($linter instanceof $base_class)) {
 
86
      throw new Exception(
 
87
        pht(
 
88
          'Expected resource "%s" to be an instance of "%s"!',
 
89
          $resource_key,
 
90
          $base_class));
 
91
    }
 
92
 
 
93
    return $linter;
 
94
  }
 
95
 
 
96
  /**
 
97
   * Build futures on this linter, for use and to share with other linters.
 
98
   *
 
99
   * @param list<string> Paths to build futures for.
 
100
   * @return list<ExecFuture> Futures.
 
101
   * @task sharing
 
102
   */
 
103
  final protected function buildSharedFutures(array $paths) {
 
104
    foreach ($paths as $path) {
 
105
      if (!isset($this->futures[$path])) {
 
106
        $this->futures[$path] = xhpast_get_parser_future($this->getData($path));
 
107
      }
 
108
    }
 
109
    return array_select_keys($this->futures, $paths);
 
110
  }
 
111
 
 
112
  /**
 
113
   * Get a path's tree from the responsible linter.
 
114
   *
 
115
   * @param   string           Path to retrieve tree for.
 
116
   * @return  XHPASTTree|null  Tree, or null if unparseable.
 
117
   * @task sharing
 
118
   */
 
119
  final protected function getXHPASTTreeForPath($path) {
 
120
 
 
121
    // If we aren't the linter responsible for actually building the parse
 
122
    // trees, go get the tree from that linter.
 
123
    if ($this->getXHPASTLinter() !== $this) {
 
124
      return $this->getXHPASTLinter()->getXHPASTTreeForPath($path);
 
125
    }
 
126
 
 
127
    if (!array_key_exists($path, $this->trees)) {
 
128
      $this->trees[$path] = null;
 
129
      try {
 
130
        $this->trees[$path] = XHPASTTree::newFromDataAndResolvedExecFuture(
 
131
          $this->getData($path),
 
132
          $this->futures[$path]->resolve());
 
133
        $root = $this->trees[$path]->getRootNode();
 
134
        $root->buildSelectCache();
 
135
        $root->buildTokenCache();
 
136
      } catch (Exception $ex) {
 
137
        $this->exceptions[$path] = $ex;
 
138
      }
 
139
    }
 
140
 
 
141
    return $this->trees[$path];
 
142
  }
 
143
 
 
144
  /**
 
145
   * Get a path's parse exception from the responsible linter.
 
146
   *
 
147
   * @param   string          Path to retrieve exception for.
 
148
   * @return  Exeption|null   Parse exception, if available.
 
149
   * @task sharing
 
150
   */
 
151
  final protected function getXHPASTExceptionForPath($path) {
 
152
    if ($this->getXHPASTLinter() !== $this) {
 
153
      return $this->getXHPASTLinter()->getXHPASTExceptionForPath($path);
 
154
    }
 
155
 
 
156
    return idx($this->exceptions, $path);
 
157
  }
 
158
 
 
159
}