/** * Scan a list of files, applying the given closure to every * AST node * * @param string[] $file_list * A list of files to scan * * @param \Closure $visit_node * A closure that is to be applied to every AST node * * @return void */ public static function scanFileList(array $file_list, \Closure $visit_node) { foreach ($file_list as $file_path) { // Convert the file to an Abstract Syntax Tree // before passing it on to the recursive version // of this method $node = \ast\parse_file($file_path, Config::get()->ast_version); // Skip empty files if (!$node) { continue; } self::scanNodeInFile($node, $file_path, $visit_node); } }
/** * Once we know what the universe looks like we * can scan for more complicated issues. * * @param CodeBase $code_base * The global code base holding all state * * @param string $file_path * A list of files to scan * * @return Context */ public static function analyzeFile(CodeBase $code_base, string $file_path) : Context { // Set the file on the context $context = (new Context())->withFile($file_path); // Convert the file to an Abstract Syntax Tree // before passing it on to the recursive version // of this method try { $node = \ast\parse_file(Config::projectPath($file_path), Config::get()->ast_version); } catch (\ParseError $parse_error) { Issue::maybeEmit($code_base, $context, Issue::SyntaxError, $parse_error->getLine(), $parse_error->getMessage()); return $context; } // Ensure we have some content if (empty($node)) { Issue::maybeEmit($code_base, $context, Issue::EmptyFile, 0, $file_path); return $context; } return (new BlockAnalysisVisitor($code_base, $context))($node); }
/** * Once we know what the universe looks like we * can scan for more complicated issues. * * @param CodeBase $code_base * The global code base holding all state * * @param string $file_path * A list of files to scan * * @return Context */ public static function analyzeFile(CodeBase $code_base, string $file_path) : Context { // Convert the file to an Abstract Syntax Tree // before passing it on to the recursive version // of this method $node = \ast\parse_file($file_path, Config::get()->ast_version); // Set the file on the context $context = (new Context())->withFile($file_path); // Ensure we have some content if (empty($node)) { Issue::emit(Issue::EmptyFile, $file_path, 0, $file_path); return $context; } // Start recursively analyzing the tree return self::analyzeNodeInContext($code_base, $context, $node); }
/** * Once we know what the universe looks like we * can scan for more complicated issues. * * @param CodeBase $code_base * The global code base holding all state * * @param string $file_path * A list of files to scan * * @return Context */ public static function analyzeFile(CodeBase $code_base, string $file_path) : Context { // Set the file on the context $context = (new Context())->withFile($file_path); // Convert the file to an Abstract Syntax Tree // before passing it on to the recursive version // of this method try { $node = \ast\parse_file($file_path, Config::get()->ast_version); } catch (\ParseError $parse_error) { Issue::maybeEmit($code_base, $context, Issue::SyntaxError, $parse_error->getLine(), $parse_error->getMessage()); return $context; } // Ensure we have some content if (empty($node)) { Issue::maybeEmit($code_base, $context, Issue::EmptyFile, 0, $file_path); return $context; } // Whenever we enter a file, we copy all global scope // variables to the local scope $context->getScope()->copyGlobalToLocal(); // Start recursively analyzing the tree return self::analyzeNodeInContext($code_base, $context, $node); }
/** * Parses and generates an AST for a single file. * * @param $path Path to the file * @param $cvsexporter A CSV exporter instance to use for exporting * the AST of the parsed file. * * @return The node index of the exported file node, or -1 if there * was an error. */ function parse_file($path, $csvexporter) : int { $finfo = new SplFileInfo($path); echo "Parsing file ", $finfo->getPathname(), PHP_EOL; try { $ast = ast\parse_file($path); // The above may throw a ParseError. We only export to CSV if that // didn't happen. $fnode = $csvexporter->store_filenode($finfo->getFilename()); $astroot = $csvexporter->export($ast); $csvexporter->store_rel($fnode, $astroot, "FILE_OF"); //echo ast_dump( $ast), PHP_EOL; } catch (ParseError $e) { $fnode = -1; error_log("[ERROR] In {$path}: " . $e->getMessage()); } return $fnode; }
/** * Once we know what the universe looks like we * can scan for more complicated issues. * * @param CodeBase $code_base * The global code base holding all state * * @param string[] $file_path_list * A list of files to scan * * @return Context */ public function analyzeFile(CodeBase $code_base, string $file_path) : Context { // Convert the file to an Abstract Syntax Tree // before passing it on to the recursive version // of this method $node = \ast\parse_file($file_path, Config::get()->ast_version); // Set the file on the context $context = (new Context())->withFile($file_path); // Ensure we have some content if (empty($node)) { Log::err(Log::EUNDEF, "Empty or missing file {$file_path}", $file_path, 0); return $context; } // Start recursively analyzing the tree return $this->analyzeNodeInContext($node, $context, $code_base); }