diff --git a/config.xsd b/config.xsd index a2412ca10..012ce9873 100644 --- a/config.xsd +++ b/config.xsd @@ -10,6 +10,7 @@ + diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 8b9f7015a..33f11a8a5 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -183,6 +183,11 @@ class Config */ protected $project_files; + /** + * @var ProjectFileFilter|null + */ + protected $extra_files; + /** * The base directory of this config file * @@ -908,6 +913,10 @@ class Config $config->project_files = ProjectFileFilter::loadFromXMLElement($config_xml->projectFiles, $base_dir, true); } + if (isset($config_xml->extraFiles)) { + $config->extra_files = ProjectFileFilter::loadFromXMLElement($config_xml->extraFiles, $base_dir, true); + } + if (isset($config_xml->taintAnalysis->ignoreFiles)) { $config->taint_analysis_ignored_files = TaintAnalysisFileFilter::loadFromXMLElement( $config_xml->taintAnalysis->ignoreFiles, @@ -1361,6 +1370,16 @@ class Config return $this->project_files && $this->project_files->allows($file_path); } + /** + * @param string $file_path + * + * @return bool + */ + public function isInExtraDirs($file_path) + { + return $this->extra_files && $this->extra_files->allows($file_path); + } + /** * @param string $file_path * @@ -1630,6 +1649,18 @@ class Config return $this->project_files->getFiles(); } + /** + * @return array + */ + public function getExtraDirectories() + { + if (!$this->extra_files) { + return []; + } + + return $this->extra_files->getDirectories(); + } + /** * @param string $file_path * diff --git a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php index 4c1c310cf..5365ba5bc 100644 --- a/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/ProjectAnalyzer.php @@ -177,6 +177,11 @@ class ProjectAnalyzer */ private $project_files = []; + /** + * @var array + */ + private $extra_files = []; + /** * @var array */ @@ -267,9 +272,9 @@ class ProjectAnalyzer $this->stdout_report_options = $stdout_report_options; $this->generated_report_options = $generated_report_options; - foreach ($this->config->getProjectDirectories() as $dir_name) { - $file_extensions = $this->config->getFileExtensions(); + $file_extensions = $this->config->getFileExtensions(); + foreach ($this->config->getProjectDirectories() as $dir_name) { $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); foreach ($file_paths as $file_path) { @@ -279,6 +284,16 @@ class ProjectAnalyzer } } + foreach ($this->config->getExtraDirectories() as $dir_name) { + $file_paths = $this->file_provider->getFilesInDir($dir_name, $file_extensions); + + foreach ($file_paths as $file_path) { + if ($this->config->isInExtraDirs($file_path)) { + $this->addExtraFile($file_path); + } + } + } + foreach ($this->config->getProjectFiles() as $file_path) { $this->addProjectFile($file_path); } @@ -548,6 +563,7 @@ class ProjectAnalyzer ) { $this->visitAutoloadFiles(); + $this->codebase->scanner->addFilesToShallowScan($this->extra_files); $this->codebase->scanner->addFilesToDeepScan($this->project_files); $this->codebase->analyzer->addFilesToAnalyze($this->project_files); @@ -1050,6 +1066,10 @@ class ProjectAnalyzer $this->project_files[$file_path] = $file_path; } + public function addExtraFile(string $file_path) : void + { + $this->extra_files[$file_path] = $file_path; + } /** * @param string $dir_name