Beispiel #1
0
 /**
  * This first pass parses code and looks for the subset
  * of issues that can be found without having to have
  * an understanding of the entire code base.
  *
  * @param CodeBase $code_base
  * The CodeBase represents state across the entire
  * code base. This is a mutable object which is
  * populated as we parse files
  *
  * @param string $file_path
  * The full path to a file we'd like to parse
  *
  * @return Context
  */
 public static function parseFile(CodeBase $code_base, string $file_path) : 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
     $node = \ast\parse_file($file_path, Config::get()->ast_version);
     if (Config::get()->dump_ast) {
         echo $file_path . "\n" . str_repeat("¯", strlen($file_path)) . "\n";
         Debug::printNode($node);
         return $context;
     }
     if (empty($node)) {
         Issue::emit(Issue::EmptyFile, $file_path, 0, $file_path);
         return $context;
     }
     return self::parseNodeInContext($code_base, $context, $node);
 }
Beispiel #2
0
 /**
  * This first pass parses code and looks for the subset
  * of issues that can be found without having to have
  * an understanding of the entire code base.
  *
  * @param CodeBase $code_base
  * The CodeBase represents state across the entire
  * code base. This is a mutable object which is
  * populated as we parse files
  *
  * @param string $file_path
  * The full path to a file we'd like to parse
  *
  * @return Context
  */
 public static function parseFile(CodeBase $code_base, string $file_path) : 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;
     }
     if (Config::get()->dump_ast) {
         echo $file_path . "\n" . str_repeat("¯", strlen($file_path)) . "\n";
         Debug::printNode($node);
         return $context;
     }
     if (empty($node)) {
         Issue::maybeEmit($code_base, $context, Issue::EmptyFile, 0, $file_path);
         return $context;
     }
     return self::parseNodeInContext($code_base, $context, $node);
 }
Beispiel #3
0
 /**
  * Accepts a visitor that differentiates on the flag value
  * of the AST node.
  *
  * @suppress PhanUnreferencedMethod
  */
 public function acceptAnyFlagVisitor(FlagVisitor $visitor)
 {
     switch ($this->node->flags) {
         case \ast\flags\ASSIGN_ADD:
             return $visitor->visitAssignAdd($this->node);
         case \ast\flags\ASSIGN_BITWISE_AND:
             return $visitor->visitAssignBitwiseAnd($this->node);
         case \ast\flags\ASSIGN_BITWISE_OR:
             return $visitor->visitAssignBitwiseOr($this->node);
         case \ast\flags\ASSIGN_BITWISE_XOR:
             return $visitor->visitAssignBitwiseXor($this->node);
         case \ast\flags\ASSIGN_CONCAT:
             return $visitor->visitAssignConcat($this->node);
         case \ast\flags\ASSIGN_DIV:
             return $visitor->visitAssignDiv($this->node);
         case \ast\flags\ASSIGN_MOD:
             return $visitor->visitAssignMod($this->node);
         case \ast\flags\ASSIGN_MUL:
             return $visitor->visitAssignMul($this->node);
         case \ast\flags\ASSIGN_POW:
             return $visitor->visitAssignPow($this->node);
         case \ast\flags\ASSIGN_SHIFT_LEFT:
             return $visitor->visitAssignShiftLeft($this->node);
         case \ast\flags\ASSIGN_SHIFT_RIGHT:
             return $visitor->visitAssignShiftRight($this->node);
         case \ast\flags\ASSIGN_SUB:
             return $visitor->visitAssignSub($this->node);
         case \ast\flags\BINARY_ADD:
             return $visitor->visitBinaryAdd($this->node);
         case \ast\flags\BINARY_BITWISE_AND:
             return $visitor->visitBinaryBitwiseAnd($this->node);
         case \ast\flags\BINARY_BITWISE_OR:
             return $visitor->visitBinaryBitwiseOr($this->node);
         case \ast\flags\BINARY_BITWISE_XOR:
             return $visitor->visitBinaryBitwiseXor($this->node);
         case \ast\flags\BINARY_BOOL_XOR:
             return $visitor->visitBinaryBoolXor($this->node);
         case \ast\flags\BINARY_CONCAT:
             return $visitor->visitBinaryConcat($this->node);
         case \ast\flags\BINARY_DIV:
             return $visitor->visitBinaryDiv($this->node);
         case \ast\flags\BINARY_IS_EQUAL:
             return $visitor->visitBinaryIsEqual($this->node);
         case \ast\flags\BINARY_IS_IDENTICAL:
             return $visitor->visitBinaryIsIdentical($this->node);
         case \ast\flags\BINARY_IS_NOT_EQUAL:
             return $visitor->visitBinaryIsNotEqual($this->node);
         case \ast\flags\BINARY_IS_NOT_IDENTICAL:
             return $visitor->visitBinaryIsNotIdentical($this->node);
         case \ast\flags\BINARY_IS_SMALLER:
             return $visitor->visitBinaryIsSmaller($this->node);
         case \ast\flags\BINARY_IS_SMALLER_OR_EQUAL:
             return $visitor->visitBinaryIsSmallerOrEqual($this->node);
         case \ast\flags\BINARY_MOD:
             return $visitor->visitBinaryMod($this->node);
         case \ast\flags\BINARY_MUL:
             return $visitor->visitBinaryMul($this->node);
         case \ast\flags\BINARY_POW:
             return $visitor->visitBinaryPow($this->node);
         case \ast\flags\BINARY_SHIFT_LEFT:
             return $visitor->visitBinaryShiftLeft($this->node);
         case \ast\flags\BINARY_SHIFT_RIGHT:
             return $visitor->visitBinaryShiftRight($this->node);
         case \ast\flags\BINARY_SPACESHIP:
             return $visitor->visitBinarySpaceship($this->node);
         case \ast\flags\BINARY_SUB:
             return $visitor->visitBinarySub($this->node);
         case \ast\flags\CLASS_ABSTRACT:
             return $visitor->visitClassAbstract($this->node);
         case \ast\flags\CLASS_FINAL:
             return $visitor->visitClassFinal($this->node);
         case \ast\flags\CLASS_INTERFACE:
             return $visitor->visitClassInterface($this->node);
         case \ast\flags\CLASS_TRAIT:
             return $visitor->visitClassTrait($this->node);
         case \ast\flags\MODIFIER_ABSTRACT:
             return $visitor->visitModifierAbstract($this->node);
         case \ast\flags\MODIFIER_FINAL:
             return $visitor->visitModifierFinal($this->node);
         case \ast\flags\MODIFIER_PRIVATE:
             return $visitor->visitModifierPrivate($this->node);
         case \ast\flags\MODIFIER_PROTECTED:
             return $visitor->visitModifierProtected($this->node);
         case \ast\flags\MODIFIER_PUBLIC:
             return $visitor->visitModifierPublic($this->node);
         case \ast\flags\MODIFIER_STATIC:
             return $visitor->visitModifierStatic($this->node);
         case \ast\flags\NAME_FQ:
             return $visitor->visitNameFq($this->node);
         case \ast\flags\NAME_NOT_FQ:
             return $visitor->visitNameNotFq($this->node);
         case \ast\flags\NAME_RELATIVE:
             return $visitor->visitNameRelative($this->node);
         case \ast\flags\PARAM_REF:
             return $visitor->visitParamRef($this->node);
         case \ast\flags\PARAM_VARIADIC:
             return $visitor->visitParamVariadic($this->node);
         case \ast\flags\RETURNS_REF:
             return $visitor->visitReturnsRef($this->node);
         case \ast\flags\TYPE_ARRAY:
             return $visitor->visitUnionTypeArray($this->node);
         case \ast\flags\TYPE_BOOL:
             return $visitor->visitUnionTypeBool($this->node);
         case \ast\flags\TYPE_CALLABLE:
             return $visitor->visitUnionTypeCallable($this->node);
         case \ast\flags\TYPE_DOUBLE:
             return $visitor->visitUnionTypeDouble($this->node);
         case \ast\flags\TYPE_LONG:
             return $visitor->visitUnionTypeLong($this->node);
         case \ast\flags\TYPE_NULL:
             return $visitor->visitUnionTypeNull($this->node);
         case \ast\flags\TYPE_OBJECT:
             return $visitor->visitUnionTypeObject($this->node);
         case \ast\flags\TYPE_STRING:
             return $visitor->visitUnionTypeString($this->node);
         case \ast\flags\UNARY_BITWISE_NOT:
             return $visitor->visitUnaryBitwiseNot($this->node);
         case \ast\flags\UNARY_BOOL_NOT:
             return $visitor->visitUnaryBoolNot($this->node);
         case \ast\flags\BINARY_BOOL_AND:
             return $visitor->visitBinaryBoolAnd($this->node);
         case \ast\flags\BINARY_BOOL_OR:
             return $visitor->visitBinaryBoolOr($this->node);
         case \ast\flags\BINARY_IS_GREATER:
             return $visitor->visitBinaryIsGreater($this->node);
         case \ast\flags\BINARY_IS_GREATER_OR_EQUAL:
             return $visitor->visitBinaryIsGreaterOrEqual($this->node);
         case \ast\flags\CLASS_ANONYMOUS:
             return $visitor->visitClassAnonymous($this->node);
         case \ast\flags\EXEC_EVAL:
             return $visitor->visitExecEval($this->node);
         case \ast\flags\EXEC_INCLUDE:
             return $visitor->visitExecInclude($this->node);
         case \ast\flags\EXEC_INCLUDE_ONCE:
             return $visitor->visitExecIncludeOnce($this->node);
         case \ast\flags\EXEC_REQUIRE:
             return $visitor->visitExecRequire($this->node);
         case \ast\flags\EXEC_REQUIRE_ONCE:
             return $visitor->visitExecRequireOnce($this->node);
         case \ast\flags\MAGIC_CLASS:
             return $visitor->visitMagicClass($this->node);
         case \ast\flags\MAGIC_DIR:
             return $visitor->visitMagicDir($this->node);
         case \ast\flags\MAGIC_FILE:
             return $visitor->visitMagicFile($this->node);
         case \ast\flags\MAGIC_FUNCTION:
             return $visitor->visitMagicFunction($this->node);
         case \ast\flags\MAGIC_LINE:
             return $visitor->visitMagicLine($this->node);
         case \ast\flags\MAGIC_METHOD:
             return $visitor->visitMagicMethod($this->node);
         case \ast\flags\MAGIC_NAMESPACE:
             return $visitor->visitMagicNamespace($this->node);
         case \ast\flags\MAGIC_TRAIT:
             return $visitor->visitMagicTrait($this->node);
         case \ast\flags\UNARY_MINUS:
             return $visitor->visitUnaryMinus($this->node);
         case \ast\flags\UNARY_PLUS:
             return $visitor->visitUnaryPlus($this->node);
         case \ast\flags\UNARY_SILENCE:
             return $visitor->visitUnarySilence($this->node);
         case \ast\flags\USE_CONST:
             return $visitor->visitUseConst($this->node);
         case \ast\flags\USE_FUNCTION:
             return $visitor->visitUseFunction($this->node);
         case \ast\flags\USE_NORMAL:
             return $visitor->visitUseNormal($this->node);
         default:
             assert(false, "All flags must match. Found " . Debug::astFlagDescription($this->node->flags ?? 0));
             break;
     }
 }
 /**
  * Visit a node with kind `\ast\AST_TYPE`
  *
  * @param Node $node
  * A node of the type indicated by the method name that we'd
  * like to figure out the type that it produces.
  *
  * @return UnionType
  * The set of types that are possibly produced by the
  * given node
  */
 public function visitType(Node $node) : UnionType
 {
     switch ($node->flags) {
         case \ast\flags\TYPE_ARRAY:
             return ArrayType::instance()->asUnionType();
         case \ast\flags\TYPE_BOOL:
             return BoolType::instance()->asUnionType();
         case \ast\flags\TYPE_CALLABLE:
             return CallableType::instance()->asUnionType();
         case \ast\flags\TYPE_DOUBLE:
             return FloatType::instance()->asUnionType();
         case \ast\flags\TYPE_LONG:
             return IntType::instance()->asUnionType();
         case \ast\flags\TYPE_NULL:
             return NullType::instance()->asUnionType();
         case \ast\flags\TYPE_OBJECT:
             return ObjectType::instance()->asUnionType();
         case \ast\flags\TYPE_STRING:
             return StringType::instance()->asUnionType();
         default:
             assert(false, "All flags must match. Found " . Debug::astFlagDescription($node->flags ?? 0));
             break;
     }
 }
Beispiel #5
0
 /**
  * Default visitor for node kinds that do not have
  * an overriding method
  *
  * @param Node $node
  * A node to parse
  *
  * @return Context
  * A new or an unchanged context resulting from
  * parsing the node
  */
 public function visit(Node $node) : Context
 {
     assert(false, "Unknown left side of assignment in {$this->context} with node type " . Debug::nodeName($node));
     return $this->visitVar($node);
 }
Beispiel #6
0
 /**
  * This first pass parses code and looks for the subset
  * of issues that can be found without having to have
  * an understanding of the entire code base.
  *
  * @param CodeBase $code_base
  * The CodeBase represents state across the entire
  * code base. This is a mutable object which is
  * populated as we parse files
  *
  * @param string $file_path
  * The full path to a file we'd like to parse
  */
 public function parseFile(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);
     $context = (new Context())->withFile($file_path);
     if (Config::get()->dump_ast) {
         echo $file_path . "\n" . str_repeat("¯", strlen($file_path)) . "\n";
         Debug::printNode($node);
         return $context;
     }
     if (empty($node)) {
         Log::err(Log::EUNDEF, "Empty or missing file  {$file_path}", $file_path, 0);
         return $context;
     }
     return $this->parseNodeInContext($code_base, $context, $node);
 }