diff --git a/src/lint/linter/ArcanistXHPASTLinter.php b/src/lint/linter/ArcanistXHPASTLinter.php
--- a/src/lint/linter/ArcanistXHPASTLinter.php
+++ b/src/lint/linter/ArcanistXHPASTLinter.php
@@ -2695,62 +2695,114 @@
   }
 
   private function lintKeywordCasing(XHPASTNode $root) {
-    $keywords = array();
-
-    $symbols = $root->selectDescendantsOfType('n_SYMBOL_NAME');
-    foreach ($symbols as $symbol) {
-      $keywords[] = head($symbol->getTokens());
-    }
-
-    $arrays = $root->selectDescendantsOfType('n_ARRAY_LITERAL');
-    foreach ($arrays as $array) {
-      $keywords[] = head($array->getTokens());
-    }
-
-    $typehints = $root->selectDescendantsOfType('n_TYPE_NAME');
-    foreach ($typehints as $typehint) {
-      $keywords[] = head($typehint->getTokens());
-    }
-
-    $new_invocations = $root->selectDescendantsOfType('n_NEW');
-    foreach ($new_invocations as $invocation) {
-      $keywords[] = head($invocation->getTokens());
-    }
+    $keywords = $root->selectTokensOfTypes(array(
+      'T_REQUIRE_ONCE',
+      'T_REQUIRE',
+      'T_EVAL',
+      'T_INCLUDE_ONCE',
+      'T_INCLUDE',
+      'T_LOGICAL_OR',
+      'T_LOGICAL_XOR',
+      'T_LOGICAL_AND',
+      'T_PRINT',
+      'T_INSTANCEOF',
+      'T_CLONE',
+      'T_NEW',
+      'T_EXIT',
+      'T_IF',
+      'T_ELSEIF',
+      'T_ELSE',
+      'T_ENDIF',
+      'T_ECHO',
+      'T_DO',
+      'T_WHILE',
+      'T_ENDWHILE',
+      'T_FOR',
+      'T_ENDFOR',
+      'T_FOREACH',
+      'T_ENDFOREACH',
+      'T_DECLARE',
+      'T_ENDDECLARE',
+      'T_AS',
+      'T_SWITCH',
+      'T_ENDSWITCH',
+      'T_CASE',
+      'T_DEFAULT',
+      'T_BREAK',
+      'T_CONTINUE',
+      'T_GOTO',
+      'T_FUNCTION',
+      'T_CONST',
+      'T_RETURN',
+      'T_TRY',
+      'T_CATCH',
+      'T_THROW',
+      'T_USE',
+      'T_GLOBAL',
+      'T_PUBLIC',
+      'T_PROTECTED',
+      'T_PRIVATE',
+      'T_FINAL',
+      'T_ABSTRACT',
+      'T_STATIC',
+      'T_VAR',
+      'T_UNSET',
+      'T_ISSET',
+      'T_EMPTY',
+      'T_HALT_COMPILER',
+      'T_CLASS',
+      'T_INTERFACE',
+      'T_EXTENDS',
+      'T_IMPLEMENTS',
+      'T_LIST',
+      'T_ARRAY',
+      'T_NAMESPACE',
+      'T_INSTEADOF',
+      'T_CALLABLE',
+      'T_TRAIT',
+      'T_YIELD',
+      'T_FINALLY',
+    ));
+    foreach ($keywords as $keyword) {
+      $value = $keyword->getValue();
 
-    $class_declarations = $root->selectDescendantsOfType('n_CLASS_DECLARATION');
-    foreach ($class_declarations as $declaration) {
-      $keywords[] = head($declaration->getTokens());
+      if ($value != strtolower($value)) {
+        $this->raiseLintAtToken(
+          $keyword,
+          self::LINT_KEYWORD_CASING,
+          pht(
+            "Convention: spell keyword '%s' as '%s'.",
+            $value,
+            strtolower($value)),
+          strtolower($value));
+      }
     }
 
-    // NOTE: Although PHP generally allows arbitrary casing for all language
-    // keywords, it's exceedingly rare for anyone to type, e.g., "CLASS" or
-    // "cLaSs" in the wild. This list just attempts to cover unconventional
-    // spellings which see some level of use, not all keywords exhaustively.
-    // There is no token or node type which spans all keywords, so this is
-    // significantly simpler.
+    $symbols = $root->selectDescendantsOfType('n_SYMBOL_NAME');
+    foreach ($symbols as $symbol) {
+      static $interesting_symbols = array(
+        'false' => true,
+        'null'  => true,
+        'true'  => true,
+      );
 
-    static $keyword_map = array(
-      'true'  => 'true',
-      'false' => 'false',
-      'null'  => 'null',
-      'array' => 'array',
-      'new'   => 'new',
-      'class' => 'class',
-    );
+      $symbol_name = $symbol->getConcreteString();
 
-    foreach ($keywords as $keyword) {
-      $value = $keyword->getValue();
-      $value_key = strtolower($value);
-      if (!isset($keyword_map[$value_key])) {
+      if ($symbol->getParentNode()->getTypeName() == 'n_FUNCTION_CALL') {
         continue;
       }
-      $expected_spelling = $keyword_map[$value_key];
-      if ($value !== $expected_spelling) {
-        $this->raiseLintAtToken(
-          $keyword,
-          self::LINT_KEYWORD_CASING,
-          "Convention: spell keyword '{$value}' as '{$expected_spelling}'.",
-          $expected_spelling);
+
+      if (idx($interesting_symbols, strtolower($symbol_name))) {
+        if ($symbol_name != strtolower($symbol_name)) {
+          $this->raiseLintAtNode(
+            $symbol,
+            self::LINT_KEYWORD_CASING,
+            pht(
+              "Convention: spell keyword '%s' as '%s'.",
+              $symbol_name,
+              strtolower($symbol_name)),
+            strtolower($symbol_name));
+        }
       }
     }
   }