private function lintModule($key, $spec, $deps)
 {
     $resolvable = array();
     $need_classes = array();
     $need_functions = array();
     $drop_modules = array();
     $used = array();
     static $types = array('class' => self::LINT_UNDECLARED_CLASS, 'interface' => self::LINT_UNDECLARED_INTERFACE, 'function' => self::LINT_UNDECLARED_FUNCTION);
     foreach ($types as $type => $lint_code) {
         foreach ($spec['requires'][$type] as $name => $places) {
             $declared = $this->checkDependency($type, $name, $deps);
             if (!$declared) {
                 $module = $this->getModuleDisplayName($key);
                 $message = $this->raiseLintInModule($key, $lint_code, "Module '{$module}' uses {$type} '{$name}' but does not include " . "any module which declares it.", $places);
                 if ($type == 'class' || $type == 'interface') {
                     $loader = new PhutilSymbolLoader();
                     $loader->setType($type);
                     $loader->setName($name);
                     $symbols = $loader->selectSymbolsWithoutLoading();
                     if ($symbols) {
                         $class_spec = reset($symbols);
                         try {
                             $loader->selectAndLoadSymbols();
                             $loaded = true;
                         } catch (PhutilMissingSymbolException $ex) {
                             $loaded = false;
                         } catch (PhutilBootloaderException $ex) {
                             $loaded = false;
                         }
                         if ($loaded) {
                             $resolvable[] = $message;
                             $need_classes[$name] = $class_spec;
                         } else {
                             if (empty($this->unknownClasses[$name])) {
                                 $this->unknownClasses[$name] = true;
                                 $library = $class_spec['library'];
                                 $this->raiseLintInModule($key, self::LINT_UNKNOWN_CLASS, "Class '{$name}' exists in the library map for library " . "'{$library}', but could not be loaded. You may need to " . "rebuild the library map.", $places);
                             }
                         }
                     } else {
                         if (empty($this->unknownClasses[$name])) {
                             $this->unknownClasses[$name] = true;
                             $this->raiseLintInModule($key, self::LINT_UNKNOWN_CLASS, "Class '{$name}' could not be found in any known library. " . "You may need to rebuild the map for the library which " . "contains it.", $places);
                         }
                     }
                 } else {
                     $loader = new PhutilSymbolLoader();
                     $loader->setType($type);
                     $loader->setName($name);
                     $symbols = $loader->selectSymbolsWithoutLoading();
                     if ($symbols) {
                         $func_spec = reset($symbols);
                         try {
                             $loader->selectAndLoadSymbols();
                             $loaded = true;
                         } catch (PhutilMissingSymbolException $ex) {
                             $loaded = false;
                         } catch (PhutilBootloaderException $ex) {
                             $loaded = false;
                         }
                         if ($loaded) {
                             $resolvable[] = $message;
                             $need_functions[$name] = $func_spec;
                         } else {
                             if (empty($this->unknownFunctions[$name])) {
                                 $this->unknownFunctions[$name] = true;
                                 $library = $func_spec['library'];
                                 $this->raiseLintInModule($key, self::LINT_UNKNOWN_FUNCTION, "Function '{$name}' exists in the library map for library " . "'{$library}', but could not be loaded. You may need to " . "rebuild the library map.", $places);
                             }
                         }
                     } else {
                         if (empty($this->unknownFunctions[$name])) {
                             $this->unknownFunctions[$name] = true;
                             $this->raiseLintInModule($key, self::LINT_UNKNOWN_FUNCTION, "Function '{$name}' could not be found in any known " . "library. You may need to rebuild the map for the library " . "which contains it.", $places);
                         }
                     }
                 }
             }
             $used[$declared] = true;
         }
     }
     $unused = array_diff_key($deps, $used);
     foreach ($unused as $unused_module_key => $ignored) {
         $module = $this->getModuleDisplayName($key);
         $unused_module = $this->getModuleDisplayName($unused_module_key);
         $resolvable[] = $this->raiseLintInModule($key, self::LINT_UNUSED_MODULE, "Module '{$module}' requires module '{$unused_module}' but does not " . "use anything it declares.", $spec['requires']['module'][$unused_module_key]);
         $drop_modules[] = $unused_module_key;
     }
     foreach ($spec['requires']['source'] as $file => $where) {
         if (empty($spec['declares']['source'][$file])) {
             $module = $this->getModuleDisplayName($key);
             $resolvable[] = $this->raiseLintInModule($key, self::LINT_UNDECLARED_SOURCE, "Module '{$module}' requires source '{$file}', but it does not " . "exist.", $where);
         }
     }
     foreach ($spec['declares']['source'] as $file => $ignored) {
         if (empty($spec['requires']['source'][$file])) {
             $module = $this->getModuleDisplayName($key);
             $resolvable[] = $this->raiseLintInModule($key, self::LINT_UNUSED_SOURCE, "Module '{$module}' does not include source file '{$file}'.", null);
         }
     }
     if ($resolvable) {
         $new_file = $this->buildNewModuleInit($key, $spec, $need_classes, $need_functions, $drop_modules);
         $init_path = $this->getModulePathOnDisk($key) . '/__init__.php';
         $root = $this->getEngine()->getWorkingCopy()->getProjectRoot();
         $try_path = Filesystem::readablePath($init_path, $root);
         $full_path = Filesystem::resolvePath($try_path, $root);
         if (Filesystem::pathExists($full_path)) {
             $init_path = $try_path;
             $old_file = Filesystem::readFile($full_path);
         } else {
             $old_file = '';
         }
         $this->willLintPath($init_path);
         $message = $this->raiseLintAtOffset(null, self::LINT_INIT_REBUILD, "This generated phutil '__init__.php' file is suggested to address " . "lint problems with static dependencies in the module.", $old_file, $new_file);
         $message->setDependentMessages($resolvable);
         foreach ($resolvable as $resolvable_message) {
             $resolvable_message->setObsolete(true);
         }
     }
 }