Return the results of parsePrimary for $file_path
Use cache and save cached results if possible

@param string|null $file_path
15147
private function GetRules( $file_path ){

		$this->SetInput($file_path);

		$cache_file = $this->CacheFile( $file_path );
		if( $cache_file ){
			if( Less_Parser::$options['cache_method'] == 'callback' ){
				if( is_callable(Less_Parser::$options['cache_callback_get']) ){
					$cache = call_user_func_array(
						Less_Parser::$options['cache_callback_get'],
						array($this, $file_path, $cache_file)
					);

					if( $cache ){
						$this->UnsetInput();
						return $cache;
					}
				}

			}elseif( file_exists($cache_file) ){
				switch(Less_Parser::$options['cache_method']){

					// Using serialize
					// Faster but uses more memory
					case 'serialize':
						$cache = unserialize(file_get_contents($cache_file));
						if( $cache ){
							touch($cache_file);
							$this->UnsetInput();
							return $cache;
						}
					break;


					// Using generated php code
					case 'var_export':
					case 'php':
					$this->UnsetInput();
					return include($cache_file);
				}
			}
		}

		$rules = $this->parsePrimary();

		if( $this->pos < $this->input_len ){
			throw new Less_Exception_Chunk($this->input, null, $this->furthest, $this->env->currentFileInfo);
		}

		$this->UnsetInput();


		//save the cache
		if( $cache_file ){
			if( Less_Parser::$options['cache_method'] == 'callback' ){
				if( is_callable(Less_Parser::$options['cache_callback_set']) ){
					call_user_func_array(
						Less_Parser::$options['cache_callback_set'],
						array($this, $file_path, $cache_file, $rules)
					);
				}

			}else{
				//msg('write cache file');
				switch(Less_Parser::$options['cache_method']){
					case 'serialize':
						file_put_contents( $cache_file, serialize($rules) );
					break;
					case 'php':
						file_put_contents( $cache_file, '<?php return '.self::ArgString($rules).'; ?>' );
					break;
					case 'var_export':
						//Requires __set_state()
						file_put_contents( $cache_file, '<?php return '.var_export($rules,true).'; ?>' );
					break;
				}

				Less_Cache::CleanCache();
			}
		}

		return $rules;
	}
508913
public static function ExtractPharPath ($real_file_path) {
		$phar_file_path = $real_file_path;
		while (!file_exists($phar_file_path)) {
			if (file_exists($phar_file_path . '.phar')) {
				preg_match("@^". $phar_file_path ."(.+)@", $real_file_path, $matches);
				return 'phar://'. $phar_file_path . '.phar' . $matches[1];
			}
			$phar_file_path = dirname($phar_file_path);
		}
		return false;
	}
453745
public function loadStatementsFromCache($file_path, $file_modified_time, $file_content_hash)
    {
        $root_cache_directory = Config::getInstance()->getCacheDirectory();

        if (!$root_cache_directory) {
            return;
        }

        $file_cache_key = $this->getParserCacheKey(
            $file_path
        );

        $parser_cache_directory = $root_cache_directory . DIRECTORY_SEPARATOR . self::PARSER_CACHE_DIRECTORY;

        $file_content_hashes = $this->new_file_content_hashes + $this->getExistingFileContentHashes();

        $cache_location = $parser_cache_directory . DIRECTORY_SEPARATOR . $file_cache_key;

        if (isset($file_content_hashes[$file_cache_key])
            && $file_content_hash === $file_content_hashes[$file_cache_key]
            && is_readable($cache_location)
            && filemtime($cache_location) > $file_modified_time
        ) {
            if ($this->use_igbinary) {
                /** @var array<int, \PhpParser\Node\Stmt> */
                $stmts = igbinary_unserialize((string)file_get_contents($cache_location));
            } else {
                /** @var array<int, \PhpParser\Node\Stmt> */
                $stmts = unserialize((string)file_get_contents($cache_location));
            }

            return $stmts;
        }
    }
640712
public function getStatementsForFile($file_path, $debug_output = false)
    {
        $from_cache = false;

        $version = (string) PHP_PARSER_VERSION . $this->this_modified_time;

        $file_contents = $this->file_provider->getContents($file_path);
        $modified_time = $this->file_provider->getModifiedTime($file_path);

        if (!$this->parser_cache_provider) {
            if ($debug_output) {
                echo 'Parsing ' . $file_path . "\n";
            }

            $stmts = self::parseStatements($file_contents, $file_path);

            return $stmts ?: [];
        }

        $file_content_hash = md5($version . $file_contents);

        $stmts = $this->parser_cache_provider->loadStatementsFromCache(
            $file_path,
            $modified_time,
            $file_content_hash
        );

        if ($stmts === null) {
            if ($debug_output) {
                echo 'Parsing ' . $file_path . "\n";
            }

            $existing_statements = $this->parser_cache_provider->loadExistingStatementsFromCache($file_path);

            if ($existing_statements && !$existing_statements[0] instanceof PhpParser\Node\Stmt) {
                $existing_statements = null;
            }

            $existing_file_contents = $this->parser_cache_provider->loadExistingFileContentsFromCache($file_path);

            // this happens after editing temporary file
            if ($existing_file_contents === $file_contents && $existing_statements) {
                $this->diff_map[$file_path] = [];
                $this->parser_cache_provider->saveStatementsToCache(
                    $file_path,
                    $file_content_hash,
                    $existing_statements,
                    true
                );

                return $existing_statements;
            }

            $file_changes = null;

            $existing_statements_copy = null;

            if ($existing_statements
                && $existing_file_contents
                && abs(strlen($existing_file_contents) - strlen($file_contents)) < 5000
            ) {
                $file_changes = \Psalm\Internal\Diff\FileDiffer::getDiff($existing_file_contents, $file_contents);

                if (count($file_changes) < 10) {
                    $traverser = new PhpParser\NodeTraverser;
                    $traverser->addVisitor(new \Psalm\Internal\Visitor\CloningVisitor);
                    // performs a deep clone
                    /** @var array<int, PhpParser\Node\Stmt> */
                    $existing_statements_copy = $traverser->traverse($existing_statements);
                } else {
                    $file_changes = null;
                }
            }

            $stmts = self::parseStatements(
                $file_contents,
                $file_path,
                $existing_file_contents,
                $existing_statements_copy,
                $file_changes
            );

            if ($existing_file_contents && $existing_statements) {
                list($unchanged_members, $unchanged_signature_members, $changed_members, $diff_map)
                    = \Psalm\Internal\Diff\FileStatementsDiffer::diff(
                        $existing_statements,
                        $stmts,
                        $existing_file_contents,
                        $file_contents
                    );

                $unchanged_members = array_map(
                    /**
                     * @param int $_
                     * @return bool
                     */
                    function ($_) {
                        return true;
                    },
                    array_flip($unchanged_members)
                );

                $unchanged_signature_members = array_map(
                    /**
                     * @param int $_
                     * @return bool
                     */
                    function ($_) {
                        return true;
                    },
                    array_flip($unchanged_signature_members)
                );

                $file_path_hash = \md5($file_path);

                $changed_members = array_map(
                    function (string $key) use ($file_path_hash) : string {
                        if (substr($key, 0, 4) === 'use:') {
                            return $key . ':' . $file_path_hash;
                        }

                        return $key;
                    },
                    $changed_members
                );

                $changed_members = array_map(
                    /**
                     * @param int $_
                     * @return bool
                     */
                    function ($_) {
                        return true;
                    },
                    array_flip($changed_members)
                );

                if (isset($this->unchanged_members[$file_path])) {
                    $this->unchanged_members[$file_path] = array_intersect_key(
                        $this->unchanged_members[$file_path],
                        $unchanged_members
                    );
                } else {
                    $this->unchanged_members[$file_path] = $unchanged_members;
                }

                if (isset($this->unchanged_signature_members[$file_path])) {
                    $this->unchanged_signature_members[$file_path] = array_intersect_key(
                        $this->unchanged_signature_members[$file_path],
                        $unchanged_signature_members
                    );
                } else {
                    $this->unchanged_signature_members[$file_path] = $unchanged_signature_members;
                }

                if (isset($this->changed_members[$file_path])) {
                    $this->changed_members[$file_path] = array_merge(
                        $this->changed_members[$file_path],
                        $changed_members
                    );
                } else {
                    $this->changed_members[$file_path] = $changed_members;
                }

                $this->diff_map[$file_path] = $diff_map;
            }

            if ($this->file_storage_cache_provider) {
                $this->file_storage_cache_provider->removeCacheForFile($file_path);
            }

            $this->parser_cache_provider->cacheFileContents($file_path, $file_contents);
        } else {
            $from_cache = true;
            $this->diff_map[$file_path] = [];
        }

        $this->parser_cache_provider->saveStatementsToCache($file_path, $file_content_hash, $stmts, $from_cache);

        if (!$stmts) {
            return [];
        }

        return $stmts;
    }
38017
public static function parseStatements(
        $file_contents,
        $file_path = null,
        string $existing_file_contents = null,
        array $existing_statements = null,
        array $file_changes = null
    ) {
        if (!self::$parser) {
            $attributes = [
                'comments', 'startLine', 'startFilePos', 'endFilePos',
            ];

            $lexer = new PhpParser\Lexer([ 'usedAttributes' => $attributes ]);

            self::$parser = (new PhpParser\ParserFactory())->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer);
        }

        $used_cached_statements = false;

        $error_handler = new \PhpParser\ErrorHandler\Collecting();

        if ($existing_statements && $file_changes && $existing_file_contents) {
            $clashing_traverser = new \Psalm\Internal\Traverser\CustomTraverser;
            $offset_analyzer = new \Psalm\Internal\Visitor\PartialParserVisitor(
                self::$parser,
                $error_handler,
                $file_changes,
                $existing_file_contents,
                $file_contents
            );
            $clashing_traverser->addVisitor($offset_analyzer);
            $clashing_traverser->traverse($existing_statements);

            if (!$offset_analyzer->mustRescan()) {
                $used_cached_statements = true;
                $stmts = $existing_statements;
            } else {
                try {
                    /** @var array<int, \PhpParser\Node\Stmt> */
                    $stmts = self::$parser->parse($file_contents, $error_handler) ?: [];
                } catch (\Throwable $t) {
                    $stmts = [];

                    // hope this got caught below
                }
            }
        } else {
            try {
                /** @var array<int, \PhpParser\Node\Stmt> */
                $stmts = self::$parser->parse($file_contents, $error_handler) ?: [];
            } catch (\Throwable $t) {
                $stmts = [];

                // hope this got caught below
            }
        }

        if ($error_handler->hasErrors() && $file_path) {
            $config = \Psalm\Config::getInstance();

            foreach ($error_handler->getErrors() as $error) {
                if ($error->hasColumnInfo()) {
                    \Psalm\IssueBuffer::add(
                        new \Psalm\Issue\ParseError(
                            $error->getMessage(),
                            new \Psalm\CodeLocation\ParseErrorLocation(
                                $error,
                                $file_contents,
                                $file_path,
                                $config->shortenFileName($file_path)
                            )
                        )
                    );
                }
            }
        }

        $resolving_traverser = new PhpParser\NodeTraverser;
        $name_resolver = new \Psalm\Internal\Visitor\SimpleNameResolver(
            $error_handler,
            $used_cached_statements ? $file_changes : []
        );
        $resolving_traverser->addVisitor($name_resolver);
        $resolving_traverser->traverse($stmts);

        return $stmts;
    }
722382
public function getFilesInDir($dir_path, array $file_extensions)
    {
        $file_paths = [];

        /** @var \RecursiveDirectoryIterator */
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir_path));
        $iterator->rewind();

        while ($iterator->valid()) {
            if (!$iterator->isDot()) {
                $extension = $iterator->getExtension();
                if (in_array($extension, $file_extensions, true)) {
                    $file_paths[] = (string)$iterator->getRealPath();
                }
            }

            $iterator->next();
        }

        return $file_paths;
    }
251528
public function cache_init($file_path)
	{
		$cache_key = md5($file_path);
		$cache_path = \Config::get('parser.View_Jade.cache_dir', null)
			.substr($cache_key, 0, 2).DS.substr($cache_key, 2, 2);

		if ($cache_path !== null AND ! is_dir($cache_path))
		{
			mkdir($cache_path, 0777, true);
		}

		static::$_cache = $cache_path;
	}
886668
private function getScannerForPath(
        $file_path,
        array $filetype_scanners,
        $will_analyze = false
    ) {
        $path_parts = explode(DIRECTORY_SEPARATOR, $file_path);
        $file_name_parts = explode('.', array_pop($path_parts));
        $extension = count($file_name_parts) > 1 ? array_pop($file_name_parts) : null;

        $file_name = $this->config->shortenFileName($file_path);

        if (isset($filetype_scanners[$extension])) {
            return new $filetype_scanners[$extension]($file_path, $file_name, $will_analyze);
        }

        return new FileScanner($file_path, $file_name, $will_analyze);
    }
1367551
def extract_path(file_path)
      return nil if file_path.nil?
      last_slash = file_path.rindex("/")
      if last_slash
        file_path[0, last_slash]
      end
    end
1006580
public static function getManipulationsForFile($file_path)
    {
        if (!isset(self::$manipulators[$file_path])) {
            return [];
        }

        $file_manipulations = [];

        foreach (self::$ordered_manipulators[$file_path] as $manipulator) {
            if ($manipulator->new_php_return_type) {
                if ($manipulator->return_typehint_start && $manipulator->return_typehint_end) {
                    $file_manipulations[$manipulator->return_typehint_start] = new FileManipulation(
                        $manipulator->return_typehint_start,
                        $manipulator->return_typehint_end,
                        $manipulator->new_php_return_type
                    );
                } else {
                    $file_manipulations[$manipulator->return_typehint_area_start] = new FileManipulation(
                        $manipulator->return_typehint_area_start,
                        $manipulator->return_typehint_area_start,
                        ': ' . $manipulator->new_php_return_type
                    );
                }
            } elseif ($manipulator->return_typehint_colon_start
                && $manipulator->new_phpdoc_return_type
                && $manipulator->return_typehint_start
                && $manipulator->return_typehint_end
            ) {
                $file_manipulations[$manipulator->return_typehint_start] = new FileManipulation(
                    $manipulator->return_typehint_colon_start,
                    $manipulator->return_typehint_end,
                    ''
                );
            }

            if (!$manipulator->new_php_return_type
                || !$manipulator->return_type_is_php_compatible
                || $manipulator->docblock_start !== $manipulator->docblock_end
            ) {
                $file_manipulations[$manipulator->docblock_start] = new FileManipulation(
                    $manipulator->docblock_start,
                    $manipulator->docblock_end,
                    $manipulator->getDocblock()
                );
            }
        }

        return $file_manipulations;
    }
1295742
public function parseFile($path)
    {
        $factory = new ParserFactory();
        $parser  = $factory->create(ParserFactory::PREFER_PHP7);

        try {
            $statements = $parser->parse($this->loadFile($path));
        } catch (Error $e) {
            throw new \RuntimeException(sprintf('Failed to parse %s file due to parse error: %s', $path, $e->getMessage()), 0, $e);
        }
        if ($statements === null) {
            throw new \RuntimeException(sprintf('Failed to parse %s', $path));
        }

        return $statements;
    }
78000
public static function remove($file_path = null, array &$logs = array())
    {
        if (is_null($file_path)) {
            return null;
        }
        if (file_exists($file_path)) {
            if (unlink($file_path)) {
                clearstatcache();
                return true;
            } else {
                $logs[] = sprintf('Can not unlink file "%s".', $file_path);
            }
        } else {
            $logs[] = sprintf('File path "%s" does not exist (can not be removed).', $file_path);
        }
        return false;
    }
568093
protected function putIntoFile($file_path, $data)
    {
        if ($this->files->isDirectory($this->files->dirname($file_path))) {
            $data = str_replace(["\n", "\r"], '', trim((string) $data));

            return $this->files->put($file_path, $data, $this->use_locking) > 0;
        }

        // @codeCoverageIgnoreStart
        return false;
        // @codeCoverageIgnoreEnd
    }
574411
public function addFileToDeepScan($file_path)
    {
        $this->files_to_scan[$file_path] = $file_path;
        $this->files_to_deep_scan[$file_path] = $file_path;
    }
1067581
public function load($file_path, Array $data = array())
    {
        $file_path = dirname(__FILE__) . '/Views/' . $file_path;

        if (!is_readable($file_path) ) {
            throw new Exception('View not found ' . $file_path . '.');
        }

        $clean_room = function($__file_name, array $__data)
        {
            extract($__data, EXTR_REFS);

            // Capture the view output
            ob_start();

            try
            {
                // Load the view within the current scope
                require $__file_name;
            }
            catch (\Exception $e)
            {
                // Delete the output buffer
                ob_end_clean();

                // Re-throw the exception
                throw $e;
            }

            // Get the captured output and close the buffer
            return ob_get_clean();
        };
        return $clean_room($file_path, $data);
    }
912364
public function has($file_path, string $file_contents = null)
    {
        $file_path = strtolower($file_path);

        if (isset(self::$storage[$file_path])) {
            return true;
        }

        if ($file_contents === null) {
            return false;
        }

        if (!$this->cache) {
            return false;
        }

        $cached_value = $this->cache->getLatestFromCache($file_path, $file_contents);

        if (!$cached_value) {
            return false;
        }

        self::$storage[$file_path] = $cached_value;
        self::$new_storage[$file_path] = $cached_value;

        return true;
    }
178744
public static function pathModeInfo(string $file_path): int
    {
        /* 如果不存在，则不可读、不可写、不可改 */
        if (!file_exists($file_path)) {
            return false;
        }

        $mark = 0;

        if (0 === stripos(PHP_OS, 'WIN')) {
            /* 测试文件 */
            $test_file = $file_path . '/cf_test.txt';

            /* 如果是目录 */
            if (is_dir($file_path)) {
                /* 检查目录是否可读 */
                $dir = @opendir($file_path);

                //如果目录打开失败，直接返回目录不可修改、不可写、不可读
                if ($dir === false) {
                    return $mark;
                }

                //目录可读 001，目录不可读 000
                if (@readdir($dir) !== false) {
                    $mark ^= 1;
                }

                @closedir($dir);

                /* 检查目录是否可写 */
                $fp = @fopen($test_file, 'wb');

                //如果目录中的文件创建失败，返回不可写。
                if ($fp === false) {
                    return $mark;
                }

                //目录可写可读 011，目录可写不可读 010
                if (@fwrite($fp, 'directory access testing.') !== false) {
                    $mark ^= 2;
                }

                @fclose($fp);
                @unlink($test_file);

                /* 检查目录是否可修改 */
                $fp = @fopen($test_file, 'ab+');
                if ($fp === false) {
                    return $mark;
                }

                if (@fwrite($fp, "modify test.\r\n") !== false) {
                    $mark ^= 4;
                }

                @fclose($fp);

                /* 检查目录下是否有执行rename()函数的权限 */
                if (@rename($test_file, $test_file) !== false) {
                    $mark ^= 8;
                }

                @unlink($test_file);

                /* 如果是文件 */
            } elseif (is_file($file_path)) {
                /* 以读方式打开 */
                $fp = @fopen($file_path, 'rb');
                if ($fp) {
                    $mark ^= 1; //可读 001
                }

                @fclose($fp);

                /* 试着修改文件 */
                $fp = @fopen($file_path, 'ab+');
                if ($fp && @fwrite($fp, '') !== false) {
                    $mark ^= 6; //可修改可写可读 111，不可修改可写可读011...
                }

                @fclose($fp);

                /* 检查目录下是否有执行rename()函数的权限 */
                if (@rename($test_file, $test_file) !== false) {
                    $mark ^= 8;
                }
            }
        } else {
            if (@is_readable($file_path)) {
                $mark ^= 1;
            }

            if (@is_writable($file_path)) {
                $mark ^= 14;
            }
        }

        return $mark;
    }