public function resolve(SourceLocation $location)
    {
        $origPath = str_replace('/', DIRECTORY_SEPARATOR, $location->path());
        $basename = basename($origPath);
        $prefixes = $this->searchPrefixes($origPath);

        $includePaths = array_filter($this->includePaths, function ($path) {
            return file_exists($path);
        });

        // Phase 1: search for an exact file match and try stripping off extra
        // folders
        foreach ($prefixes as $prefix) {
            foreach ($includePaths as $path) {
                $file = implode(DIRECTORY_SEPARATOR, [$path, $prefix, $basename]);
                if (file_exists($file)) {
                    return new SourceLocation($this->realRelativePath($file, $path), $location->line());
                }
            }
        }

        // Phase 2: recursively search folders for a matching file
        foreach ($includePaths as $includePath) {
            $iterator = new MatchingFileIterator(
                $includePath,
                $origPath
            );
            foreach ($iterator as $file => $info) {
                return new SourceLocation($this->realRelativePath($file, $includePath), $location->line());
            }
        }

        return null;
    }